From 3b0307e53fe6a9246a5602df1c3de82406b06aab Mon Sep 17 00:00:00 2001 From: Martin Desruisseaux Date: Mon, 18 Mar 2024 15:33:35 +0100 Subject: [PATCH 01/20] Beginning of ISO 19111 revision: - Add the `CoordinateSet` and `CoordinateMetadata` interfaces. - Partial edition of packages documentation. --- geoapi-pending/src/main/java/module-info.java | 1 + .../opengis/annotation/ResourceBundles.java | 2 +- .../coordinate/CoordinateMetadata.java | 71 ++++++++++++ .../org/opengis/coordinate/CoordinateSet.java | 88 +++++++++++++++ .../org/opengis/coordinate/package-info.java | 37 +++++++ .../org/opengis/geometry/DirectPosition.java | 13 ++- .../opengis/referencing/crs/CompoundCRS.java | 6 +- .../referencing/crs/EngineeringCRS.java | 2 +- .../referencing/crs/GeocentricCRS.java | 2 +- .../referencing/crs/GeographicCRS.java | 16 +-- .../opengis/referencing/crs/ProjectedCRS.java | 8 +- .../opengis/referencing/crs/SingleCRS.java | 10 +- .../opengis/referencing/crs/TemporalCRS.java | 4 +- .../opengis/referencing/crs/VerticalCRS.java | 6 +- .../opengis/referencing/crs/package-info.java | 103 ++++-------------- .../opengis/referencing/cs/AxisDirection.java | 4 +- .../opengis/referencing/cs/package-info.java | 92 ++++------------ .../opengis/referencing/datum/ImageDatum.java | 3 +- .../referencing/datum/package-info.java | 40 +++---- .../referencing/operation/Conversion.java | 16 +-- .../referencing/operation/package-info.java | 32 +++--- .../org/opengis/referencing/package-info.java | 65 +++++------ .../java/org/opengis/util/ScopedName.java | 4 +- .../opengis/annotation/class-index.properties | 2 + geoapi/src/pending/java/module-info.java | 1 + .../java/org/opengis/geoapi/Content.java | 2 + .../java/org/opengis/geoapi/NameSpaces.java | 1 + 27 files changed, 360 insertions(+), 271 deletions(-) create mode 100644 geoapi/src/main/java/org/opengis/coordinate/CoordinateMetadata.java create mode 100644 geoapi/src/main/java/org/opengis/coordinate/CoordinateSet.java create mode 100644 geoapi/src/main/java/org/opengis/coordinate/package-info.java diff --git a/geoapi-pending/src/main/java/module-info.java b/geoapi-pending/src/main/java/module-info.java index 2945c41e8..ee18b4f03 100644 --- a/geoapi-pending/src/main/java/module-info.java +++ b/geoapi-pending/src/main/java/module-info.java @@ -57,6 +57,7 @@ exports org.opengis.referencing.cs; exports org.opengis.referencing.crs; exports org.opengis.referencing.operation; + exports org.opengis.coordinate; exports org.opengis.geometry; exports org.opengis.geometry.coordinate; exports org.opengis.feature; diff --git a/geoapi/src/main/java/org/opengis/annotation/ResourceBundles.java b/geoapi/src/main/java/org/opengis/annotation/ResourceBundles.java index 690cd3976..d7e12615c 100644 --- a/geoapi/src/main/java/org/opengis/annotation/ResourceBundles.java +++ b/geoapi/src/main/java/org/opengis/annotation/ResourceBundles.java @@ -143,5 +143,5 @@ public static Properties classIndex() throws IOException { /** * Number of lines in the {@code "class-index.properties"} file. */ - static final int INDEX_CAPACITY = 245; + static final int INDEX_CAPACITY = 247; } diff --git a/geoapi/src/main/java/org/opengis/coordinate/CoordinateMetadata.java b/geoapi/src/main/java/org/opengis/coordinate/CoordinateMetadata.java new file mode 100644 index 000000000..2820478ca --- /dev/null +++ b/geoapi/src/main/java/org/opengis/coordinate/CoordinateMetadata.java @@ -0,0 +1,71 @@ +/* + * GeoAPI - Java interfaces for OGC/ISO standards + * Copyright © 2024 Open Geospatial Consortium, Inc. + * http://www.geoapi.org + * + * Licensed 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.opengis.coordinate; + +import java.util.Optional; +import java.time.temporal.Temporal; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.annotation.UML; + +import static org.opengis.annotation.Obligation.*; +import static org.opengis.annotation.Specification.*; + + +/** + * Metadata required to reference coordinates. + * A {@linkplain CoordinateReferenceSystem coordinate reference system} (CRS) is mandatory. + * If the CRS is dynamic, then a coordinate epoch is also mandatory. + * Whether the CRS is dynamic is determined through the CRS's reference frame definition. + * + * @author Martin Desruisseaux (Geomatys) + * @version 3.1 + * @since 3.1 + */ +@UML(identifier="CoordinateMetadata", specification=ISO_19111) +public interface CoordinateMetadata { + /** + * The coordinate reference system (CRS) in which the coordinate tuples are given. + * + * @departure easeOfUse + * The ISO specification defines two conditional attributes: an identifier ({@code crsID}) or an association + * to a CRS object ({@code crs}), with the requirement that at least one of them shall be supplied. + * GeoAPI retains only the latter for client applications ease of use, therefor making this attribute mandatory. + * Implementers shall resolve identifiers, for example using {@link org.opengis.referencing.crs.CRSAuthorityFactory}. + * + * @return the coordinate reference system (CRS) of coordinate tuples. + */ + @UML(identifier="crs", obligation=MANDATORY, specification=ISO_19111) + CoordinateReferenceSystem getCoordinateReferenceSystem(); + + /** + * Date at which coordinate tuples referenced to a dynamic CRS are valid. + * It should be an object from the {@link java.time} package such as {@link java.time.Instant}. + * This attribute is required if the CRS is dynamic. + * + * @departure integration + * The ISO specification uses a decimal year in the Gregorian calendar. + * For example, 2017-03-25 in the Gregorian calendar is epoch 2017.23. + * GeoAPI delegates to the Java time package instead. + * + * @return epoch at which coordinate tuples are valid. + */ + @UML(identifier="coordinateEpoch", obligation=CONDITIONAL, specification=ISO_19111) + default Optional getCoordinateEpoch() { + return Optional.empty(); + } +} diff --git a/geoapi/src/main/java/org/opengis/coordinate/CoordinateSet.java b/geoapi/src/main/java/org/opengis/coordinate/CoordinateSet.java new file mode 100644 index 000000000..948a2b4df --- /dev/null +++ b/geoapi/src/main/java/org/opengis/coordinate/CoordinateSet.java @@ -0,0 +1,88 @@ +/* + * GeoAPI - Java interfaces for OGC/ISO standards + * Copyright © 2024 Open Geospatial Consortium, Inc. + * http://www.geoapi.org + * + * Licensed 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.opengis.coordinate; + +import java.util.Iterator; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; +import org.opengis.geometry.DirectPosition; +import org.opengis.annotation.UML; + +import static org.opengis.annotation.Obligation.*; +import static org.opengis.annotation.Specification.*; + + +/** + * A collection of coordinate tuples referenced to the same coordinate reference system (CRS). + * If the CRS is dynamic, the {@code CoordinateSet} metadata contains also a coordinate epoch. + * Operations on the geometry of the tuples within the coordinate set are valid only if all + * tuples are referenced to the same coordinate epoch. + * + *

Coordinate operations

+ * Coordinate sets referenced to one CRS may be referenced to another CRS through the + * application of a {@linkplain org.opengis.referencing.operation.CoordinateOperation coordinate operation}. + * If the CRS is dynamic, the {@code CoordinateSet} may be converted to another coordinate epoch + * through a point motion coordinate operation that includes time evolution. + * + * @author Martin Desruisseaux (Geomatys) + * @version 3.1 + * @since 3.1 + */ +@UML(identifier="CoordinateSet", specification=ISO_19111) +public interface CoordinateSet extends Iterable { + /** + * Coordinate metadata to which this coordinate set is referenced. Coordinate metadata includes a + * {@linkplain org.opengis.referencing.crs.CoordinateReferenceSystem coordinate reference system} + * (CRS) and, if the CRS is dynamic, a coordinate epoch. + * + * @return coordinate metadata to which this coordinate set is referenced. + */ + @UML(identifier="coordinateMetadata", obligation=MANDATORY, specification=ISO_19111) + CoordinateMetadata getCoordinateMetadata(); + + /** + * Returns the number of dimensions of coordinate tuples. This is determined by the + * {@linkplain CoordinateMetadata#getCoordinateReferenceSystem() coordinate reference system}. + * + * @return the number of dimensions of coordinate tuples. + */ + default int getDimension() { + // All methods invoked below are for attributes declared as mandatory. Values shall not be null. + return getCoordinateMetadata().getCoordinateReferenceSystem().getCoordinateSystem().getDimension(); + } + + /** + * Returns the positions described by coordinate tuples. + * + * @return position described by coordinate tuples. + */ + @Override + @UML(identifier="coordinateTuple", obligation=MANDATORY, specification=ISO_19111) + Iterator iterator(); + + /** + * Returns a stream of coordinate tuples. + * Whether the stream is sequential or parallel is implementation dependent. + * The default implementation creates a sequential stream. + * + * @return a sequential or parallel stream of coordinate tuples. + */ + default Stream stream() { + return StreamSupport.stream(spliterator(), false); + } +} diff --git a/geoapi/src/main/java/org/opengis/coordinate/package-info.java b/geoapi/src/main/java/org/opengis/coordinate/package-info.java new file mode 100644 index 000000000..e2a64817c --- /dev/null +++ b/geoapi/src/main/java/org/opengis/coordinate/package-info.java @@ -0,0 +1,37 @@ +/* + * GeoAPI - Java interfaces for OGC/ISO standards + * Copyright © 2008-2024 Open Geospatial Consortium, Inc. + * http://www.geoapi.org + * + * Licensed 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. + */ + +/** + * Tuple of coordinate values. + * A coordinate is one of n scalar values that define the position of a single point. + * A coordinate tuple is an ordered list of coordinates that define the position of a single point. + * The {@linkplain org.opengis.geometry.DirectPosition#getCoordinates() coordinates} within a coordinate tuple + * are mutually independent, and the number of coordinates is equal to the tuple + * {@linkplain org.opengis.geometry.DirectPosition#getDimension() dimension}. + * A coordinate set is a collection of coordinate tuples referenced to the same + * {@linkplain org.opengis.referencing.crs.CoordinateReferenceSystem coordinate reference system}. + * A coordinate set does not necessarily describe a geometry. + * + *

Coordinate tuples can be represented by instances of {@link org.opengis.geometry.DirectPosition} + * or by plain Java arrays of numbers.

+ * + * @author Martin Desruisseaux (Geomatys) + * @version 3.1 + * @since 3.1 + */ +package org.opengis.coordinate; diff --git a/geoapi/src/main/java/org/opengis/geometry/DirectPosition.java b/geoapi/src/main/java/org/opengis/geometry/DirectPosition.java index 374304e65..eae495999 100644 --- a/geoapi/src/main/java/org/opengis/geometry/DirectPosition.java +++ b/geoapi/src/main/java/org/opengis/geometry/DirectPosition.java @@ -1,6 +1,6 @@ /* * GeoAPI - Java interfaces for OGC/ISO standards - * Copyright © 2003-2023 Open Geospatial Consortium, Inc. + * Copyright © 2003-2024 Open Geospatial Consortium, Inc. * http://www.geoapi.org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,9 +33,9 @@ * (such as {@linkplain org.opengis.geometry.Geometry geometries}) that have references to * {@linkplain CoordinateReferenceSystem coordinate reference system} (CRS), * the {@link #getCoordinateReferenceSystem()} method may return {@code null} if this particular - * {@code DirectPosition} is included in a larger object with such a reference to a CRS. + * {@code DirectPosition} is included in a larger object with such a reference to a CRS. * In this case, the coordinate reference system is implicitly assumed to take on the value - * of the containing object's CRS. + * of the containing object's CRS. * *

Optional operation

* A direct position can optionally be modifiable. If this {@code DirectPosition} is unmodifiable, @@ -46,7 +46,7 @@ * GeoAPI moved this interface into the {@code org.opengis.geometry} root package for * convenience, because it is extensively used. * - * @author Martin Desruisseaux (IRD) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.1 * @since 1.0 */ @@ -68,11 +68,11 @@ default DirectPosition getDirectPosition() { * May be {@code null} if this particular {@code DirectPosition} is included in a larger object * with such a reference to a {@linkplain CoordinateReferenceSystem coordinate reference system}. * In this case, the coordinate reference system is implicitly assumed to take on the value - * of the containing object's CRS. + * of the containing object's CRS. * *

Default implementation

* The default implementation returns {@code null}. Implementations should override - * this method if the CRS is known or can be taken from the containing object. + * this method if the CRS is known or can be taken from the containing object. * * @return the coordinate reference system (CRS), or {@code null}. */ @@ -93,6 +93,7 @@ default CoordinateReferenceSystem getCoordinateReferenceSystem() { /** * A copy of the coordinates stored as an array of double values. * Changes to the returned array will not affect this {@code DirectPosition}. + * The array length shall be equal to the {@linkplain #getDimension() dimension}. * *

Default implementation

* The default implementation invokes {@link #getCoordinate(int)} for all indices diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/CompoundCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/CompoundCRS.java index c845b5f25..a96bb511f 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/CompoundCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/CompoundCRS.java @@ -27,9 +27,9 @@ /** - * A coordinate reference system describing the position of points through two or more - * independent coordinate reference systems. Thus it is indirectly associated with two - * or more {@linkplain org.opengis.referencing.cs.CoordinateSystem coordinate systems} + * A CRS describing the position of points through two or more independent CRSs. + * Thus it is indirectly associated with two or more + * {@linkplain org.opengis.referencing.cs.CoordinateSystem coordinate systems} * and {@linkplain org.opengis.referencing.datum.Datum datums} by defining the compound * CRS as an ordered set of two or more instances of {@link CoordinateReferenceSystem}. * diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/EngineeringCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/EngineeringCRS.java index 47fd74765..e184e4dcb 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/EngineeringCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/EngineeringCRS.java @@ -27,7 +27,7 @@ /** - * A 1-, 2- or 3-dimensional contextually local coordinate reference system. + * A 1-, 2- or 3-dimensional contextually local CRS. * It can be divided into two broad categories: * *
    diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/GeocentricCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/GeocentricCRS.java index 5433926cb..9faaf9ab5 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/GeocentricCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/GeocentricCRS.java @@ -29,7 +29,7 @@ /** - * A 3-dimensional coordinate reference system with the origin at the approximate centre of mass of the earth. + * A 3-dimensional CRS with the origin at the approximate centre of mass of the earth. * A geocentric CRS deals with the earth's curvature by taking a 3-dimensional spatial view, which obviates * the need to model the earth's curvature. * diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/GeographicCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/GeographicCRS.java index afed66c99..da2febaf8 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/GeographicCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/GeographicCRS.java @@ -27,14 +27,16 @@ /** - * A 2- or 3-dimensional coordinate reference system based on an ellipsoidal approximation of the geoid. - * This provides an accurate representation of the geometry of geographic features for a large - * portion of the earth's surface. + * A 2- or 3-dimensional CRS based on an ellipsoidal approximation of the geoid. + * This provides an accurate representation of the geometry of geographic features for a large portion of the earth's surface. + * A 2D geographic CRS is used when positions of features are described on the surface of the reference ellipsoid. + * A 3D geographic CRS is used when positions are described on, above or below the reference ellipsoid. * - *

    A Geographic CRS is not suitable for mapmaking on a planar surface, because it describes geometry - * on a curved surface. It is impossible to represent such geometry in a Euclidean plane without - * introducing distortions. The need to control these distortions has given rise to the development - * of the science of {@linkplain org.opengis.referencing.operation.Projection map projections}.

    + *

    A geographic CRS is not suitable for mapmaking on a planar surface, + * because it describes geometry on a curved surface. + * It is impossible to represent such geometry in a Euclidean plane without introducing distortions. + * The need to control these distortions has given rise to the development of the science of + * {@linkplain org.opengis.referencing.operation.Projection map projections}.

    * *

    This type of CRS can be used with coordinate systems of type * {@link org.opengis.referencing.cs.EllipsoidalCS}.

    diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/ProjectedCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/ProjectedCRS.java index 02d32ee38..317cab426 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/ProjectedCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/ProjectedCRS.java @@ -29,10 +29,10 @@ /** - * A 2-dimensional coordinate reference system used to approximate the shape of the earth on a planar surface. - * It is done in such a way that the distortion that is inherent to the approximation is carefully - * controlled and known. Distortion correction is commonly applied to calculated bearings and - * distances to produce values that are a close match to actual field values. + * A 2- or 3-dimensional CRS based on an approximation of the shape of the earth's surface by a plane. + * It is done in such a way that the distortion that is inherent to the approximation is carefully controlled and known. + * Distortion correction is commonly applied to calculated bearings and distances + * to produce values that are a close match to actual field values. * *

    This type of CRS can be used with coordinate systems of type * {@link org.opengis.referencing.cs.CartesianCS}.

    diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/SingleCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/SingleCRS.java index c3442f725..a26083d99 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/SingleCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/SingleCRS.java @@ -28,7 +28,7 @@ /** - * Base type of {@linkplain CoordinateSystem coordinate systems} related to an object by a {@linkplain Datum datum}. + * Base type of CRS related to an object by a datum. * For {@linkplain org.opengis.referencing.datum.GeodeticDatum geodetic} * and {@linkplain org.opengis.referencing.datum.VerticalDatum vertical} datums, the object will be the Earth. * @@ -48,6 +48,9 @@ public interface SingleCRS extends CoordinateReferenceSystem { /** * Returns the coordinate system associated to this CRS. + * The coordinate system is composed of a set of coordinate axes with specified units of measure. + * This concept implies the mathematical rules that define how coordinate values are calculated + * from distances, angles and other geometric elements and vice versa. */ @Override @UML(identifier="coordinateSystem", obligation=MANDATORY, specification=ISO_19111) @@ -58,6 +61,11 @@ public interface SingleCRS extends CoordinateReferenceSystem { * In the case of {@link GeneralDerivedCRS}, this method returns the * datum of the {@linkplain GeneralDerivedCRS#getBaseCRS() base CRS}. * + *

    A datum specifies the relationship of a coordinate system to the object, thus ensuring that the abstract + * mathematical concept “coordinate system” can be applied to the practical problem of describing positions of + * features on or near the earth's surface by means of coordinates. The object will generally, but not necessarily, + * be the earth. For certain coordinate reference systems, the object may be a moving platform.

    + * * @return the datum. * * @departure easeOfUse diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/TemporalCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/TemporalCRS.java index efe166ff1..93c264d0e 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/TemporalCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/TemporalCRS.java @@ -27,7 +27,9 @@ /** - * A 1-dimensional coordinate reference system used for the recording of time. + * A 1-dimensional CRS used for the recording of time. + * Any CRS can be associate with a temporal CRS to form a spatio-temporal {@link CompoundCRS}. + * More than one temporal CRS may be included if these axes represent different time quantities. * *

    This type of CRS can be used with coordinate systems of type * {@link org.opengis.referencing.cs.TimeCS}.

    diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/VerticalCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/VerticalCRS.java index 6d43dab0e..3cf2df102 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/VerticalCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/VerticalCRS.java @@ -27,9 +27,9 @@ /** - * A 1-dimensional coordinate reference system used for recording heights or depths. Vertical CRSs make use - * of the direction of gravity to define the concept of height or depth, but the relationship with - * gravity may not be straightforward. + * A 1-dimensional CRS used for recording heights or depths. + * Vertical CRSs make use of the direction of gravity to define the concept of height or depth, + * but the relationship with gravity may not be straightforward. * *

    By implication, ellipsoidal heights (h) cannot be captured in a vertical coordinate * reference system. Ellipsoidal heights cannot exist independently, but only as inseparable part diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/package-info.java b/geoapi/src/main/java/org/opengis/referencing/crs/package-info.java index b2df3adfa..e1a586922 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/package-info.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/package-info.java @@ -17,24 +17,15 @@ */ /** - * {@linkplain org.opengis.referencing.crs.CoordinateReferenceSystem Coordinate reference systems} - * ({@linkplain org.opengis.referencing.cs.CoordinateSystem coordinate systems} with a - * {@linkplain org.opengis.referencing.datum.Datum datum}). The following is adapted from - * {@linkplain org.opengis.annotation.Specification#ISO_19111 OpenGIS® Spatial Referencing by - * Coordinates (Topic 2)} specification. - * - *

    A coordinate reference system (CRS) consists of one coordinate system (CS) that is related to the earth - * or platform through one datum. The coordinate system is composed of a set of coordinate axes with specified - * units of measure. This concept implies the mathematical rules that define how coordinate values are calculated - * from distances, angles and other geometric elements and vice versa.

    - * - *

    A datum specifies the relationship of a coordinate system to the object, thus ensuring that the abstract - * mathematical concept “coordinate system” can be applied to the practical problem of describing positions of - * features on or near the earth's surface by means of coordinates. The object will generally, but not necessarily, - * be the earth; for certain coordinate reference systems, the object may be a moving platform.

    + * Reference systems by coordinates. + * A {@linkplain org.opengis.referencing.crs.CoordinateReferenceSystem Coordinate Reference System} (CRS) + * consists of one {@linkplain org.opengis.referencing.cs Coordinate System} + * (a set of {@linkplain org.opengis.referencing.cs.CoordinateSystemAxis axes} with implied mathematical rules + * for calculating distances and angles from coordinates) that is related to the Earth, another celestial body + * or a platform through one {@linkplain org.opengis.referencing.datum datum}. * *

    {@code CoordinateReferenceSystem} instances and their components shall be immutable. - * For CRS defined on moving platforms such as cars, ships, aircraft and spacecraft, + * For CRS defined on moving platforms such as cars, ships, aircraft and spacecraft, * transformation to an earth-fixed coordinate reference system may include a time element. * Time-variability of coordinate reference systems may be covered by creating different * {@code CoordinateReferenceSystem} instances, each with a different datum, for consecutive epochs. @@ -43,79 +34,25 @@ * and coordinate reference systems.

    * *

    Sub-types of coordinate reference system

    - *

    Geodetic survey practice usually divides coordinate reference systems into a number of sub-types. + * Geodetic survey practice usually divides coordinate reference systems into a number of sub-types. * The common classification criterion for sub-typing of coordinate reference systems can be described * as the way in which they deal with earth curvature. This has a direct effect on the portion of the - * earth's surface that can be covered by that type of CRS with an acceptable degree of error. - * Thus the following principal sub-types of coordinate reference system are distinguished:

    - * - *
    - *

    Geocentric: - * Type of coordinate reference system that deals with the earth's curvature by taking the 3D spatial view, - * which obviates the need to model the earth's curvature. - * The origin of a geocentric CRS is at the approximate centre of mass of the earth.

    - * - *

    Geographic: - * Type of coordinate reference system based on an ellipsoidal approximation of the geoid. - * This provides an accurate representation of the geometry of geographic features for a large portion - * of the earth's surface. Geographic coordinate reference systems can be 2D or 3D. - * A 2D Geographic CRS is used when positions of features are described on the surface of the reference ellipsoid; - * a 3D Geographic CRS is used when positions are described on, above or below the reference ellipsoid.

    - * - *

    Projected: - * Type of coordinate reference system that is based on an approximation of the shape of the earth's surface by a plane. - * The distortion that is inherent to the approximation is carefully controlled and known. - * Distortion correction is commonly applied to calculated bearings and distances - * to produce values that are a close match to actual field values.

    - * - *

    Engineering: - * Type of coordinate reference system that is that is used only in a contextually local sense. - * This sub-type is used to model two broad categories of local coordinate reference systems:

    - *
      - *
    • earth-fixed systems, applied to engineering activities on or near the surface of the earth;
    • - *
    • coordinates on moving platforms such as road vehicles, vessels, aircraft or spacecraft.
    • - *
    + * earth's surface that can be covered by that type of CRS with an acceptable degree of error. * - *

    Image: - * An Image CRS is an Engineering CRS applied to images. Image CRSs are treated as - * a separate sub-type because a separate user community exists for images with its - * own vocabulary. The definition of the associated Image Datum contains two data - * attributes not relevant for other datums and coordinate reference systems.

    - * - *

    Vertical: - * Type of coordinate reference system used for the recording of heights or depths. - * Vertical CRSs make use of the direction of gravity to define the concept of height or depth, - * but its relationship with gravity may not be straightforward. - * By implication ellipsoidal heights (h) cannot be captured in a vertical CRS. - * Ellipsoidal heights cannot exist independently, but only as inseparable part of a 3D coordinate tuple - * defined in a geographic 3D coordinate reference system.

    - * - *

    Temporal: - * Used for the recording of time in association with any of the listed spatial coordinate reference systems. - * Any CRS can be associate with a temporal CRS to form a spatio-temporal compound CRS. - * More than one temporal CRS may be included if these axes represent different time quantities.

    - *
    - * - *

    In addition to the above principal sub-types, so called because they represent concepts generally known - * in geodetic practice, two more sub-types have been defined to permit modelling of certain relationships - * and constraints that exist between the principal sub-types.

    - * - *
    - *

    Compound: + *

    Compound CRS

    * The traditional separation of horizontal and vertical position has resulted in coordinate reference systems * that are horizontal (2D) in nature and vertical (1D). It is established practice to combine the horizontal - * coordinates of a point with a height or depth from a different CRS. The coordinate reference system to which - * these 3D coordinates are referenced combines the separate horizontal and vertical coordinate reference systems - * of the horizontal and vertical coordinates. Such a CRS is called a compound CRS. - * It consists of an ordered sequence of the two or more single coordinate reference systems.

    - * - *

    Derived: - * Some coordinate reference systems are defined by applying a coordinate conversion to another CRS. - * Such a CRS is called a derived CRS and the coordinate reference system it was derived from - * by applying the conversion is called the source or base CRS. + * coordinates of a point with a height or depth from a different CRS. The coordinate reference system + * to which these 3D coordinates are referenced combines the separate horizontal and vertical coordinate reference + * systems of the horizontal and vertical coordinates. Such a CRS is called a compound + * CRS. It consists of an ordered sequence of the two or more single coordinate reference systems. + * + *

    Derived CRS

    + * Some coordinate reference systems are defined by applying a coordinate conversion to another CRS. + * Such a CRS is called a derived CRS and the coordinate reference system it + * was derived from by applying the conversion is called the source or base CRS. * A coordinate conversion is an arithmetic operation with zero or more parameters that have defined values. - * The base CRS and derived CRS have the same datum.

    - *
    + * The base CRS and derived CRS have the same datum. * * @author Martin Desruisseaux (IRD) * @version 3.1 diff --git a/geoapi/src/main/java/org/opengis/referencing/cs/AxisDirection.java b/geoapi/src/main/java/org/opengis/referencing/cs/AxisDirection.java index fea864b60..af6cbc45d 100644 --- a/geoapi/src/main/java/org/opengis/referencing/cs/AxisDirection.java +++ b/geoapi/src/main/java/org/opengis/referencing/cs/AxisDirection.java @@ -56,8 +56,8 @@ public final class AxisDirection extends CodeList { public static final AxisDirection OTHER = new AxisDirection("OTHER"); /** - * Axis positive direction is north. In a geographic or projected CRS, - * north is defined through the geodetic datum. In an engineering CRS, + * Axis positive direction is north. In a geographic or projected CRS, + * north is defined through the geodetic datum. In an engineering CRS, * north may be defined with respect to an engineering object rather * than a geographical direction. * diff --git a/geoapi/src/main/java/org/opengis/referencing/cs/package-info.java b/geoapi/src/main/java/org/opengis/referencing/cs/package-info.java index 132f83eb1..6df43837e 100644 --- a/geoapi/src/main/java/org/opengis/referencing/cs/package-info.java +++ b/geoapi/src/main/java/org/opengis/referencing/cs/package-info.java @@ -17,82 +17,34 @@ */ /** - * {@linkplain org.opengis.referencing.cs.CoordinateSystem Coordinate systems} and their - * {@linkplain org.opengis.referencing.cs.CoordinateSystemAxis axis}. The following is adapted from - * {@linkplain org.opengis.annotation.Specification#ISO_19111 OpenGIS® Spatial Referencing by - * Coordinates (Topic 2)} specification. - * - *

    A coordinate system shall be composed of a non-repeating sequence of coordinate system axes. - * One {@link org.opengis.referencing.cs.CoordinateSystem} (CS) instance may be used by multiple - * {@linkplain org.opengis.referencing.crs.CoordinateReferenceSystem} (CRS) instances. - * The dimension of the coordinate space, the names, the units of measure, the directions - * and sequence of the axes shall be part of the coordinate system definition. - * The number of axes shall be equal to the dimension of the space of which it describes the geometry. - * It is therefore not permitted to supply a coordinate tuple with two heights of different definition.

    - * - *

    The {@linkplain org.opengis.geometry.DirectPosition#getDimension() number of coordinates} in a coordinate tuple - * shall be equal to the {@linkplain org.opengis.referencing.cs.CoordinateSystem#getDimension() number of coordinate - * axes} in the coordinate system. Coordinates in coordinate tuples shall be supplied in the order in which - * the coordinate system's axes are defined.

    - * - *

    A coordinate system implies how coordinates are calculated from geometric elements such as distances - * and angles and vice versa. The calculus required to derive angles and distances from point coordinates - * and vice versa in a map plane is simple Euclidean 2D arithmetic. To do the same on the surface of an - * ellipsoid (curved 2D space) involves more complex ellipsoidal calculus. These rules cannot be specified - * in detail, but are implied in the geometric properties of the coordinate space.

    - * - *

    Coordinate system types and unions

    - *

    Coordinate systems are divided into subtypes by the geometric properties of the coordinate space spanned - * and the geometric properties of the axes themselves (straight or curved; perpendicular or not). + * Coordinate Systems and their axes. + * A {@linkplain org.opengis.referencing.cs.CoordinateSystem coordinate system} (CS) shall be + * composed of a non-repeating sequence of {@linkplain org.opengis.referencing.cs.CoordinateSystemAxis axes}. + * Each axis can have have a name, an abbreviation, a unit of measure, a direction and a range of values. + * The number of axes is the dimension of the coordinate space. Axis order is significant. + * + *

    One {@link org.opengis.referencing.cs.CoordinateSystem} instance may be used by multiple + * {@link org.opengis.referencing.crs.CoordinateReferenceSystem} (CRS) instances. + * The {@linkplain org.opengis.geometry.DirectPosition#getDimension() number of coordinates} in a coordinate tuple + * shall be equal to the {@linkplain org.opengis.referencing.cs.CoordinateSystem#getDimension() number of coordinate axes} + * in the coordinate system. + * Coordinates in coordinate tuples shall be supplied in the order in which the coordinate system's axes are defined.

    + * + *

    Coordinate system types

    + * A coordinate system implies how coordinates are calculated from geometric elements such as distances and + * angles and vice versa. These rules are not specified in details, but are implied by the coordinate system type. * Certain subtypes of coordinate system shall be used only with specific subtypes of coordinate reference system. - * The restrictions are documented in the javadoc of each CRS subtype.

    - * - *

    ISO 19111 defines three coordinate system unions in addition to the coordinate system types. - * Each union enumerates the coordinate system types that can be associated to a CRS type. - * However, the {@code union} construct found in some languages like C/C++ is not available in Java. - * GeoAPI workarounds this limitation in different ways:

    + * The restrictions are documented in the javadoc of each CRS subtype. * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Representations of Coordinate System unions
    UnionTypes in the unionGeoAPI approach
    {@code GeodeticCS}{@link org.opengis.referencing.cs.CartesianCS}, - * {@link org.opengis.referencing.cs.EllipsoidalCS}, - * {@link org.opengis.referencing.cs.SphericalCS}Provides a {@link org.opengis.referencing.crs.GeographicCRS} type for the {@code EllipsoidalCS} case. - * Provides distinct {@link org.opengis.referencing.crs.CRSFactory} methods for the {@code CartesianCS} - * and {@code SphericalCS} cases.
    {@code EngineeringCS}{@link org.opengis.referencing.cs.AffineCS}, - * {@link org.opengis.referencing.cs.CartesianCS}, - * {@link org.opengis.referencing.cs.CylindricalCS}, - * {@link org.opengis.referencing.cs.LinearCS}, - * {@link org.opengis.referencing.cs.PolarCS}, - * {@link org.opengis.referencing.cs.SphericalCS}, - * {@link org.opengis.referencing.cs.UserDefinedCS}.No workaround in the API. Verified by the conformance tests.
    {@code ImageCS}{@link org.opengis.referencing.cs.AffineCS}, - * {@link org.opengis.referencing.cs.CartesianCS}Defines {@code CartesianCS} as a special case of {@code AffineCS}.
    + *

    ISO 19111 defines some coordinate system unions in addition to the coordinate system types. + * Each union enumerates the coordinate system types that can be associated to a CRS type. + * GeoAPI does not define those unions because they have no direct equivalence in the Java language.

    * * @departure constraint - * ISO 19111 defines {@code GeodeticCS}, {@code EngineeringCS} and {@code ImageCS} unions. + * ISO 19111 defines {@code GeodeticCS} and {@code EngineeringCS} unions. * However, the {@code union} construct found in some languages like C/C++ is not available in Java. * For each union, a different approach has been applied and documented in the {@code org.opengis.referencing.cs} - * package. In the particular case of {@code ImageCS}, the same type-safety objective can be obtained - * through a slight change in the interface hierarchy. + * package. * * @author Martin Desruisseaux (IRD) * @version 3.1 diff --git a/geoapi/src/main/java/org/opengis/referencing/datum/ImageDatum.java b/geoapi/src/main/java/org/opengis/referencing/datum/ImageDatum.java index e6dfb4173..681448700 100644 --- a/geoapi/src/main/java/org/opengis/referencing/datum/ImageDatum.java +++ b/geoapi/src/main/java/org/opengis/referencing/datum/ImageDatum.java @@ -31,7 +31,8 @@ * *
    Note: * the image datum definition applies regardless of whether or not the image is georeferenced. - * Georeferencing is performed through a transformation of image CRS to geodetic or projected CRS. + * Georeferencing is performed through a transformation of image CRS to geodetic + * or projected CRS. * The transformation plays no part in the image datum definition.
    * * @author Martin Desruisseaux (IRD) diff --git a/geoapi/src/main/java/org/opengis/referencing/datum/package-info.java b/geoapi/src/main/java/org/opengis/referencing/datum/package-info.java index 559d58299..9a7470dde 100644 --- a/geoapi/src/main/java/org/opengis/referencing/datum/package-info.java +++ b/geoapi/src/main/java/org/opengis/referencing/datum/package-info.java @@ -17,22 +17,17 @@ */ /** - * {@linkplain org.opengis.referencing.datum.Datum Geodetic datum} (the relationship of a - * {@linkplain org.opengis.referencing.cs.CoordinateSystem coordinate system} to the earth). - * The following is adapted from - * {@linkplain org.opengis.annotation.Specification#ISO_19111 OpenGIS® Spatial Referencing by - * Coordinates (Topic 2)} specification. - * - *

    A datum can be used as the basis for one-, two- or three-dimensional systems. + * Relationship of a Coordinate System (CS) to the Earth, another celestial body or a platform. + * A datum can be used as the basis for one-, two- or three-dimensional systems. * For {@linkplain org.opengis.referencing.crs.GeodeticCRS geodetic} * and {@linkplain org.opengis.referencing.crs.VerticalCRS vertical} coordinate reference systems, * the datum shall relate the coordinate system to the Earth. * With other types of coordinate reference systems (CRS), the datum may relate the coordinate system * to another physical or virtual object. In some applications of an - * {@linkplain org.opengis.referencing.crs.EngineeringCRS Engineering CRS}, the object may be a platform - * moving relative to the Earth. In these applications, the datum itself is not time-dependent, - * but any transformations of the associated coordinates to an Earth-fixed or other coordinate reference system - * shall contain time-dependent parameters.

    + * {@linkplain org.opengis.referencing.crs.EngineeringCRS Engineering CRS}, + * the object may be a platform moving relative to the Earth. In these applications, + * the datum itself is not time-dependent, but any transformations of the associated coordinates + * to an Earth-fixed or other coordinate reference system shall contain time-dependent parameters. * *

    Five subtypes of datum are specified: * {@linkplain org.opengis.referencing.datum.GeodeticDatum geodetic}, @@ -98,10 +93,9 @@ * for the instantaneous atmospheric pressure at sea level and the height of the * point above MSL.

    * - *

    In meteorology, atmospheric pressure routinely takes the role - * as vertical coordinate in a CRS that is used as a spatial reference frame for - * meteorological parameters in the upper atmosphere. The origin of the datum - * is in that case the (hypothetical) zero atmospheric pressure and the positive + *

    In meteorology, atmospheric pressure routinely takes the role as vertical coordinate in a CRS + * that is used as a spatial reference frame for meteorological parameters in the upper atmosphere. + * The origin of the datum is in that case the (hypothetical) zero atmospheric pressure and the positive * vertical axis points down (to increasing pressure).

    * *
  • Other surface
    @@ -114,7 +108,7 @@ *

    Image datum

    *

    The image pixel grid is defined as the set of lines of constant * integer coordinate values. The term "image grid" is often used in other standards to - * describe the concept of Image CRS. However, care must be taken to correctly interpret + * describe the concept of Image CRS. However, care must be taken to correctly interpret * this term in the context in which it is used. The term "grid cell" is often used as a * substitute for the term "pixel".

    * @@ -155,13 +149,13 @@ * specification shall not be provided if the datum type not geodetic.

    * *

    One ellipsoid must be specified with every geodetic datum, - * even if the ellipsoid is not used computationally. The latter may be the case - * when a Geocentric CRS is used, e.g., in the calculation of satellite orbit and - * ground positions from satellite observations. Although use of a Geocentric CRS - * apparently obviates the need of an ellipsoid, the ellipsoid usually played a role - * in the determination of the associated geodetic datum. Furthermore, one or more - * Geographic CRSs may be based on the same geodetic datum, which requires the correct - * ellipsoid the associated with any given geodetic datum.

    + * even if the ellipsoid is not used computationally. + * The latter may be the case when a Geocentric CRS is used, + * e.g., in the calculation of satellite orbit and ground positions from satellite observations. + * Although use of a Geocentric CRS apparently obviates the need of an ellipsoid, + * the ellipsoid usually played a role in the determination of the associated geodetic datum. + * Furthermore, one or more Geographic CRSs may be based on the same geodetic datum, + * which requires the correct ellipsoid the associated with any given geodetic datum.

    * *

    An ellipsoid is defined either by its semi-major axis and * inverse flattening, or by its semi-major axis and semi-minor axis. For some diff --git a/geoapi/src/main/java/org/opengis/referencing/operation/Conversion.java b/geoapi/src/main/java/org/opengis/referencing/operation/Conversion.java index 41fefc217..cdcb98edc 100644 --- a/geoapi/src/main/java/org/opengis/referencing/operation/Conversion.java +++ b/geoapi/src/main/java/org/opengis/referencing/operation/Conversion.java @@ -48,22 +48,22 @@ @UML(identifier="CC_Conversion", specification=ISO_19111, version=2007) public interface Conversion extends SingleOperation { /** - * Returns the source CRS. Conversions may have a source CRS that - * is not specified here, but through - * {@link org.opengis.referencing.crs.GeneralDerivedCRS#getBaseCRS()} instead. + * Returns the source CRS. + * Conversions may have a source CRS that is not specified here, + * but through {@link org.opengis.referencing.crs.GeneralDerivedCRS#getBaseCRS()} instead. * - * @return the source CRS, or {@code null} if not available. + * @return the source CRS, or {@code null} if not available. */ @Override @UML(identifier="sourceCRS", obligation=OPTIONAL, specification=ISO_19111) CoordinateReferenceSystem getSourceCRS(); /** - * Returns the target CRS. {@linkplain Conversion Conversions} may have a target CRS - * that is not specified here, but through - * {@link org.opengis.referencing.crs.GeneralDerivedCRS} instead. + * Returns the target CRS. + * Conversions may have a target CRS that is not specified here, + * but through {@link org.opengis.referencing.crs.GeneralDerivedCRS} instead. * - * @return the target CRS, or {@code null} if not available. + * @return the target CRS, or {@code null} if not available. */ @Override @UML(identifier="targetCRS", obligation=OPTIONAL, specification=ISO_19111) diff --git a/geoapi/src/main/java/org/opengis/referencing/operation/package-info.java b/geoapi/src/main/java/org/opengis/referencing/operation/package-info.java index f8a43c4d5..f65b28e78 100644 --- a/geoapi/src/main/java/org/opengis/referencing/operation/package-info.java +++ b/geoapi/src/main/java/org/opengis/referencing/operation/package-info.java @@ -17,11 +17,10 @@ */ /** - * {@linkplain org.opengis.referencing.operation.CoordinateOperation Coordinate operations} (relationship between - * any two {@linkplain org.opengis.referencing.crs.CoordinateReferenceSystem coordinate reference systems}). - * The following is adapted from - * {@linkplain org.opengis.annotation.Specification#ISO_19111 OpenGIS® Spatial Referencing by - * Coordinates (Topic 2)} specification. + * Coordinate operations (relationship between any two CRS). + * Coordinates may be changed to be referenced to a different CRS. + * If the CRS is dynamic, coordinates also may be referenced to a different coordinate epoch, + * or to both a different CRS and different coordinate epoch. * *

    If the relationship between any two coordinate reference * systems is known, coordinates can be transformed or converted to another @@ -53,12 +52,11 @@ * transformation method, parameter values and accuracy characteristics.

  • *
* - *

A coordinate operation (transformation or conversion) can be - * time-varying, and must be time-varying if either the source or target CRS is time - * varying. When the coordinate operation is time-varying, the operation method used - * will also be time-varying, and some of the parameters used by that operation method - * will involve time. For example, some of the parameters may have time, velocity, and/or - * acceleration values and units.

+ *

A coordinate operation (transformation or conversion) can be time-varying, + * and must be time-varying if either the source or target CRS is time varying. + * When the coordinate operation is time-varying, the operation method used will also be time-varying, + * and some of the parameters used by that operation method will involve time. + * For example, some of the parameters may have time, velocity, and/or acceleration values and units.

* *

Coordinate conversions

*

Coordinate conversions are coordinate operations that make use @@ -68,7 +66,7 @@ * fixed arithmetic relationship. Additionally one of the two tuples cannot exist * without specification of the coordinate conversion and the 'source' coordinate * reference system. Coordinate conversions are therefore intimately related to the - * concept of {@linkplain org.opengis.referencing.crs.DerivedCRS Derived CRS}.

+ * concept of {@linkplain org.opengis.referencing.crs.DerivedCRS Derived CRS}.

* *

The best-known example of this source-derived relationship * is a {@linkplain org.opengis.referencing.crs.ProjectedCRS projected coordinate reference system}, @@ -93,11 +91,11 @@ * conversions. Concatenated coordinate operations may contain coordinate transformations * and/or coordinate conversions.

* - *

The source and target coordinate reference system of a - * coordinate conversion are defined in the {@link org.opengis.referencing.crs.GeneralDerivedCRS}, - * by specifying the base (i.e., source) CRS and the defining conversion. The derived - * coordinate reference system itself is the target CRS in this situation. When used - * in a concatenated operation, the conversion's source and target coordinate reference + *

The source and target coordinate reference system of a coordinate conversion + * are defined in the {@link org.opengis.referencing.crs.GeneralDerivedCRS}, + * by specifying the base (i.e., source) CRS and the defining conversion. + * The derived coordinate reference system itself is the target CRS in this situation. + * When used in a concatenated operation, the conversion's source and target coordinate reference * system are equally subject to the above constraint as the source and target of a * transformation although they are specified in a different manner.

* diff --git a/geoapi/src/main/java/org/opengis/referencing/package-info.java b/geoapi/src/main/java/org/opengis/referencing/package-info.java index 9081d3a48..ae7a728d3 100644 --- a/geoapi/src/main/java/org/opengis/referencing/package-info.java +++ b/geoapi/src/main/java/org/opengis/referencing/package-info.java @@ -17,47 +17,38 @@ */ /** - * Base interfaces for {@linkplain org.opengis.referencing.ReferenceSystem reference systems}. The following - * is adapted from {@linkplain org.opengis.annotation.Specification#ISO_19111 OpenGIS® Spatial Referencing by - * Coordinates (Topic 2)} specification. - * - *

A reference system contains the metadata required to interpret spatial location information unambiguously. - * The description of an object's attributes can be done

- * - *
    - *
  • explicitly, by providing all defining parameters, or
  • - *
  • by identifier, a reference to a recognised source that contains a full description of the object.
  • - *
- * - * The {@link org.opengis.referencing.IdentifiedObject} interface contains attributes common to several objects - * used in spatial referencing by coordinates. For example, a {@linkplain org.opengis.referencing.datum.Datum datum} - * {@linkplain org.opengis.referencing.IdentifiedObject#getName() primary names} might be North American Datum - * of 1983. This may have alternative names or {@linkplain org.opengis.referencing.IdentifiedObject#getAlias() - * aliases}, for example the abbreviation “NAD83”. + * Base interfaces for reference systems by coordinates or by identifiers. + * A reference system contains the metadata required to interpret spatial location information unambiguously. + * Referencing can be done by coordinates with interfaces in the {@code crs} sub-package, + * or by identifiers with interfaces in the {@code gazetteer} sub-package. + * The {@link org.opengis.referencing.IdentifiedObject} interface in this package + * contains attributes common to several objects used in referencing by coordinates or by identifiers. + * For example, a reference frame {@linkplain org.opengis.referencing.IdentifiedObject#getName() primary name} + * might be North American Datum of 1983. That reference frame may have alternative names or + * {@linkplain org.opengis.referencing.IdentifiedObject#getAlias() aliases}, + * for example, the abbreviation NAD83. * *

Another attribute is {@linkplain org.opengis.referencing.IdentifiedObject#getIdentifiers() identifiers}. - * This is a unique code used to reference an object in a given place. For example, an external geodetic register might - * give the NAD83 datum a unique code of “6269”. Identifiers have a data type of {@link org.opengis.metadata.Identifier}. - * In addition to the use of an identifier as a reference to a definition in a remote register, it may also be included - * in an object definition to allow remote users to refer to the object.

- * - *

Most interfaced objects are immutable. This means that implementations promise - * not to change an object's internal state once they have handed out an interface pointer. Since - * most interfaced objects are specified to be immutable, there do not need to be any constraints - * on operation sequencing. This means that these interfaces can be used in parallel computing - * environments (e.g. Internet servers).

+ * This is a unique code used to reference an object in a given place. + * For example, an external geodetic register might give the NAD83 reference frame a unique code of 6269. + * Objects can be obtained from codes using sub-interfaces of {@link org.opengis.referencing.AuthorityFactory}. + * Identifiers have a data type of {@link org.opengis.metadata.Identifier}.

* *

Well-Known Text format

- *

Many entities in this specification can be printed in a well-known text format. - * This allows objects to be stored in databases (persistence), and transmitted between - * interoperating computer programs. Well-Known Texts (WKT) may come in two formats: - * - *

    - *
  • The current standard, WKT 2, is defined by {@linkplain org.opengis.annotation.Specification#ISO_19162 ISO 19162}.
  • - *
  • The legacy format, WKT 1, was defined by {@linkplain org.opengis.annotation.Specification#OGC_01009 OGC 01-009}.
  • - *
- * - * @author Martin Desruisseaux (IRD) + * Many entities can be printed in a + * {@linkplain org.opengis.annotation.Specification#ISO_19162 Well-Known Text (WKT)} format + * by invoking the {@link org.opengis.referencing.IdentifiedObject#toWKT()} method. + * This allows objects to be stored in databases (persistence), + * and transmitted between inter-operating computer programs. + * + *

Immutability

+ * Most interfaced objects are immutable. This means that implementations should not + * change an object's internal state once they have handed out an interface pointer. + * Since most interfaced objects are specified to be immutable, + * there do not need to be any constraints on operation sequencing. + * This means that these interfaces can be used in parallel computing environments (e.g. Internet servers). + * + * @author Martin Desruisseaux (IRD, Geomatys) * @author Ely Conn (Leica Geosystems Geospatial Imaging, LLC) * @version 3.1 * @since 1.0 diff --git a/geoapi/src/main/java/org/opengis/util/ScopedName.java b/geoapi/src/main/java/org/opengis/util/ScopedName.java index c80028aec..0c3e170a8 100644 --- a/geoapi/src/main/java/org/opengis/util/ScopedName.java +++ b/geoapi/src/main/java/org/opengis/util/ScopedName.java @@ -173,8 +173,8 @@ public interface ScopedName extends GenericName { * into a legal string representation of the name. There will be variants on this theme. * XML aficionados may require URIs. For Java classes, a dotted notation is more appropriate, * for C/C++, a double-colon, for directories, a forward or reverse slash, - * and for {@linkplain org.opengis.referencing.crs.CoordinateReferenceSystem CRS}, it - * will depend on the mode of expression: URN or {@code Authority:Identifier} notation. + * and for {@linkplain org.opengis.referencing.crs.CoordinateReferenceSystem CRS}, + * it will depend on the mode of expression: URN or {@code Authority:Identifier} notation. * *
Analogy: * this method is similar in purpose to the {@link java.io.File#toString() File.toString()} diff --git a/geoapi/src/main/resources/org/opengis/annotation/class-index.properties b/geoapi/src/main/resources/org/opengis/annotation/class-index.properties index 5cb3691c1..21431dbd7 100644 --- a/geoapi/src/main/resources/org/opengis/annotation/class-index.properties +++ b/geoapi/src/main/resources/org/opengis/annotation/class-index.properties @@ -53,6 +53,8 @@ CS_SphericalCS=org.opengis.referencing.cs.SphericalCS CS_TimeCS=org.opengis.referencing.cs.TimeCS CS_UserDefinedCS=org.opengis.referencing.cs.UserDefinedCS CS_VerticalCS=org.opengis.referencing.cs.VerticalCS +CoordinateMetadata=org.opengis.coordinate.CoordinateMetadata +CoordinateSet=org.opengis.coordinate.CoordinateSet DCPList=org.opengis.metadata.identification.DistributedComputingPlatform DQM_BasicMeasure=org.opengis.metadata.quality.BasicMeasure DQM_Description=org.opengis.metadata.quality.Description diff --git a/geoapi/src/pending/java/module-info.java b/geoapi/src/pending/java/module-info.java index beead4d1d..5b8073dce 100644 --- a/geoapi/src/pending/java/module-info.java +++ b/geoapi/src/pending/java/module-info.java @@ -67,6 +67,7 @@ exports org.opengis.referencing.cs; exports org.opengis.referencing.crs; exports org.opengis.referencing.operation; + exports org.opengis.coordinate; exports org.opengis.geometry; exports org.opengis.geometry.coordinate; exports org.opengis.feature; diff --git a/geoapi/src/shared/java/org/opengis/geoapi/Content.java b/geoapi/src/shared/java/org/opengis/geoapi/Content.java index 8890bb93b..ca930a289 100644 --- a/geoapi/src/shared/java/org/opengis/geoapi/Content.java +++ b/geoapi/src/shared/java/org/opengis/geoapi/Content.java @@ -122,6 +122,8 @@ public enum Content { org.opengis.geometry .DirectPosition .class, org.opengis.geometry .Envelope .class, org.opengis.geometry .Geometry .class, + org.opengis.coordinate .CoordinateMetadata .class, + org.opengis.coordinate .CoordinateSet .class, org.opengis.geometry.primitive .Point .class, org.opengis.metadata.acquisition .Instrument .class, org.opengis.metadata.acquisition .Platform .class, diff --git a/geoapi/src/shared/java/org/opengis/geoapi/NameSpaces.java b/geoapi/src/shared/java/org/opengis/geoapi/NameSpaces.java index be75a65d0..7ec97aedd 100644 --- a/geoapi/src/shared/java/org/opengis/geoapi/NameSpaces.java +++ b/geoapi/src/shared/java/org/opengis/geoapi/NameSpaces.java @@ -148,6 +148,7 @@ public QName name(final Class type, final Map Date: Mon, 18 Mar 2024 18:59:39 +0100 Subject: [PATCH 02/20] Review of the `org.opengis.referencing` package (not yet sub-packages). --- .../test/referencing/PseudoEpsgFactory.java | 19 --- .../example/referencing/SimpleTransform.java | 17 +++ .../referencing/TransformedCoordinateSet.java | 129 ++++++++++++++++++ .../org/opengis/coordinate/CoordinateSet.java | 5 +- .../opengis/referencing/AuthorityFactory.java | 76 +++++++---- .../opengis/referencing/IdentifiedObject.java | 14 +- .../opengis/referencing/ObjectFactory.java | 5 +- .../opengis/referencing/ReferenceSystem.java | 2 +- .../operation/CoordinateOperation.java | 65 ++++++++- .../util/UnimplementedServiceException.java | 4 +- .../opengis/annotation/class-index.properties | 2 +- .../referencing/AuthorityFactoryTest.java | 4 +- 12 files changed, 270 insertions(+), 72 deletions(-) create mode 100644 geoapi-examples/src/main/java/org/opengis/example/referencing/TransformedCoordinateSet.java diff --git a/geoapi-conformance/src/main/java/org/opengis/test/referencing/PseudoEpsgFactory.java b/geoapi-conformance/src/main/java/org/opengis/test/referencing/PseudoEpsgFactory.java index b7fb273bc..7bc77074f 100644 --- a/geoapi-conformance/src/main/java/org/opengis/test/referencing/PseudoEpsgFactory.java +++ b/geoapi-conformance/src/main/java/org/opengis/test/referencing/PseudoEpsgFactory.java @@ -34,7 +34,6 @@ import org.opengis.referencing.operation.*; import org.opengis.metadata.citation.Citation; import org.opengis.util.FactoryException; -import org.opengis.util.InternationalString; import org.opengis.test.util.PseudoFactory; import org.opengis.test.ValidatorContainer; import org.opengis.test.Units; @@ -211,24 +210,6 @@ public Set getAuthorityCodes(final Class typ return Collections.emptySet(); } - /** - * Returns a description of the object corresponding to a code. - * The default implementation returns {@code null}. - * - * @param code value allocated by authority. - * @return a description of the object, or {@code null} if the object - * corresponding to the specified {@code code} has no description. - * @throws FactoryException if this method cannot provide the requested information. - * - * @deprecated This method is ambiguous. - */ - @Override - @SuppressWarnings("removal") - @Deprecated(since = "3.1", forRemoval = true) - public InternationalString getDescriptionText(final String code) throws FactoryException { - return null; - } - /** * Builds a map of properties for a referencing object to be built. The map shall contain * at least the {@link IdentifiedObject#NAME_KEY} identifier associated to the given value. diff --git a/geoapi-examples/src/main/java/org/opengis/example/referencing/SimpleTransform.java b/geoapi-examples/src/main/java/org/opengis/example/referencing/SimpleTransform.java index 3dde6caa5..3a01d8317 100644 --- a/geoapi-examples/src/main/java/org/opengis/example/referencing/SimpleTransform.java +++ b/geoapi-examples/src/main/java/org/opengis/example/referencing/SimpleTransform.java @@ -7,6 +7,7 @@ import java.util.Arrays; import java.util.Objects; +import org.opengis.coordinate.CoordinateSet; import org.opengis.metadata.citation.Citation; import org.opengis.geometry.DirectPosition; @@ -105,6 +106,22 @@ public int getTargetDimensions() { return targetCRS.getCoordinateSystem().getDimension(); } + /** + * Changes coordinates from source CRS to target CRS. + * The default implementation transform the coordinate tuples immediately and stores the result. + * This is okay for small coordinate set, but inefficient for large ones. + * + * @param data the coordinates to change. + * @return the result of changing coordinates. + * @throws TransformException if some coordinates cannot be changed. + * Note that this exception not being thrown is not a guarantee that the computation + * will not fail later, for example during a stream terminal operation. + */ + @Override + public CoordinateSet transform(final CoordinateSet data) throws TransformException { + return new TransformedCoordinateSet(this, data); + } + /** * Gets the math transform, which is represented directly by {@code this} implementation * class since it does not distinguish operation and transform. diff --git a/geoapi-examples/src/main/java/org/opengis/example/referencing/TransformedCoordinateSet.java b/geoapi-examples/src/main/java/org/opengis/example/referencing/TransformedCoordinateSet.java new file mode 100644 index 000000000..e61953d12 --- /dev/null +++ b/geoapi-examples/src/main/java/org/opengis/example/referencing/TransformedCoordinateSet.java @@ -0,0 +1,129 @@ +/* + * GeoAPI - Java interfaces for OGC/ISO standards + * This file is hereby placed into the Public Domain. + * This means anyone is free to do whatever they wish with this file. + */ +package org.opengis.example.referencing; + +import java.util.Arrays; +import java.util.Objects; +import java.util.Iterator; +import java.util.Optional; +import java.util.stream.Stream; +import java.time.temporal.Temporal; +import org.opengis.geometry.DirectPosition; +import org.opengis.coordinate.CoordinateSet; +import org.opengis.coordinate.CoordinateMetadata; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.CoordinateOperation; +import org.opengis.referencing.operation.MathTransform; +import org.opengis.referencing.operation.TransformException; + + +/** + * The result of transforming coordinate tuples using the math transform of a given coordinate operation. + * This class is used for the default implementation of {@link SimpleTransform#transform(CoordinateSet)}. + * This default implementation is okay for small set but should not be used for large ones. + * + * @author Martin Desruisseaux (Geomatys) + * @version 3.1 + * @since 3.1 + */ +final class TransformedCoordinateSet implements CoordinateSet, CoordinateMetadata { + /** + * The CRS of the transformed coordinate tuples. + * + * @see #getCoordinateReferenceSystem() + */ + private final CoordinateReferenceSystem crs; + + /** + * Date at which coordinate tuples are valid, or {@code null} if the CRS is not dynamic. + * + * @see #getCoordinateEpoch() + */ + private final Temporal epoch; + + /** + * The transformed coordinate tuples. + * + * @see #iterator() + * @see #stream() + */ + private final DirectPosition[] positions; + + /** + * Creates a new transformed coordinate set. + * + * @param operation the coordinate operation to apply. + * @param data the coordinate tuples to transform. + * @throws TransformException if the data cannot be changed. + */ + TransformedCoordinateSet(final CoordinateOperation operation, final CoordinateSet data) throws TransformException { + final CoordinateMetadata md = data.getCoordinateMetadata(); + crs = Objects.requireNonNull(operation.getTargetCRS(), "Missing target CRS."); + if (!crs.equals(md.getCoordinateReferenceSystem())) { + throw new TransformException("Unexpected data CRS."); + } + epoch = operation.getTargetEpoch().orElse(null); + if (!Objects.equals(epoch, md.getCoordinateEpoch())) { + throw new TransformException("Missing or unexpected data epoch."); + } + final MathTransform mt = operation.getMathTransform(); + try { + positions = data.stream().sequential().map((p) -> { + try { + return mt.transform(p, null); + } catch (TransformException e) { + throw new RuntimeException(e); // Checked exception not allowed here. + } + }).toArray(DirectPosition[]::new); + } catch (RuntimeException e) { + final Throwable cause = e.getCause(); + if (cause instanceof TransformException) { + throw (TransformException) cause; // The checked exception that we couldn't throw in above lambda. + } + throw e; + } + } + + /** + * Returns the coordinate metadata to which this coordinate set is referenced. + */ + @Override + public CoordinateMetadata getCoordinateMetadata() { + return this; + } + + /** + * Returns the CRS in which the coordinate tuples are given. + */ + @Override + public CoordinateReferenceSystem getCoordinateReferenceSystem() { + return crs; + } + + /** + * Returns the date at which coordinate tuples referenced to a dynamic CRS are valid. + */ + @Override + public Optional getCoordinateEpoch() { + return Optional.ofNullable(epoch); + } + + /** + * Returns the transformed positions described by coordinate tuples. + */ + @Override + public Iterator iterator() { + return Arrays.asList(positions).iterator(); + } + + /** + * Returns a stream of transformed coordinate tuples. + */ + @Override + public Stream stream() { + return Arrays.stream(positions); + } +} diff --git a/geoapi/src/main/java/org/opengis/coordinate/CoordinateSet.java b/geoapi/src/main/java/org/opengis/coordinate/CoordinateSet.java index 948a2b4df..f34891b50 100644 --- a/geoapi/src/main/java/org/opengis/coordinate/CoordinateSet.java +++ b/geoapi/src/main/java/org/opengis/coordinate/CoordinateSet.java @@ -41,7 +41,10 @@ * * @author Martin Desruisseaux (Geomatys) * @version 3.1 - * @since 3.1 + * + * @see org.opengis.referencing.operation.CoordinateOperation#transform(CoordinateSet) + * + * @since 3.1 */ @UML(identifier="CoordinateSet", specification=ISO_19111) public interface CoordinateSet extends Iterable { diff --git a/geoapi/src/main/java/org/opengis/referencing/AuthorityFactory.java b/geoapi/src/main/java/org/opengis/referencing/AuthorityFactory.java index 468dc39f6..c45fa49cb 100644 --- a/geoapi/src/main/java/org/opengis/referencing/AuthorityFactory.java +++ b/geoapi/src/main/java/org/opengis/referencing/AuthorityFactory.java @@ -18,25 +18,28 @@ package org.opengis.referencing; import java.util.Set; +import java.util.Optional; import org.opengis.metadata.citation.Citation; import org.opengis.util.Factory; import org.opengis.util.FactoryException; import org.opengis.util.InternationalString; import org.opengis.util.UnimplementedServiceException; import org.opengis.annotation.UML; + +import static org.opengis.annotation.Obligation.*; import static org.opengis.annotation.Specification.*; /** - * Base interface for all authority factories. An authority is an organization - * that maintains definitions of authority codes. An authority code is a compact - * string defined by an authority to reference a particular spatial reference object. + * Base interface for all authority factories. + * An authority is an organization that maintains definitions of authority codes. + * An authority code is a compact string defined by an authority to reference a particular referencing object. * - *

For example, the European Petroleum Survey Group (EPSG) maintains - * a database of coordinate systems, and other spatial referencing objects, where each object has a code - * number ID. For example, the EPSG code for a WGS84 Lat/Lon coordinate system is “4326”.

+ *

For example, the European Petroleum Survey Group (EPSG) maintains a database + * of coordinate reference systems, and other spatial referencing objects, where each object has a code number ID. + * For example, the EPSG code for a WGS84 Lat/Lon CRS is 4326.

* - * @author Martin Desruisseaux (IRD) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.1 * @since 1.0 */ @@ -54,26 +57,23 @@ public interface AuthorityFactory extends Factory { * Returns the set of authority codes for objects of the given type. * The {@code type} argument specifies the base type of identified objects. * - *

Example: if this factory is an instance of {@link org.opengis.referencing.crs.CRSAuthorityFactory}, - * then:

- * - *
    - *
  • {@linkplain org.opengis.referencing.crs.CoordinateReferenceSystem}.class
    - * asks for all authority codes accepted by one of - * {@link org.opengis.referencing.crs.CRSAuthorityFactory#createGeographicCRS createGeographicCRS}, - * {@link org.opengis.referencing.crs.CRSAuthorityFactory#createProjectedCRS createProjectedCRS}, - * {@link org.opengis.referencing.crs.CRSAuthorityFactory#createVerticalCRS createVerticalCRS}, - * {@link org.opengis.referencing.crs.CRSAuthorityFactory#createTemporalCRS createTemporalCRS} - * and any other method returning a sub-type of {@code CoordinateReferenceSystem}.

  • - *
  • {@linkplain org.opengis.referencing.crs.ProjectedCRS}.class
    - * asks only for authority codes accepted by - * {@link org.opengis.referencing.crs.CRSAuthorityFactory#createProjectedCRS createProjectedCRS}.

  • - *
+ *

Example

+ * Assuming that this factory is an instance of {@link org.opengis.referencing.crs.CRSAuthorityFactory}, + * if the {@code type} argument value is set to + * {@linkplain org.opengis.referencing.crs.CoordinateReferenceSystem}.class, + * then this method should return all authority codes accepted by methods such as + * {@link org.opengis.referencing.crs.CRSAuthorityFactory#createGeographicCRS createGeographicCRS(…)}, + * {@link org.opengis.referencing.crs.CRSAuthorityFactory#createProjectedCRS createProjectedCRS(…)}, + * {@link org.opengis.referencing.crs.CRSAuthorityFactory#createVerticalCRS createVerticalCRS(…)}, + * {@link org.opengis.referencing.crs.CRSAuthorityFactory#createTemporalCRS createTemporalCRS(…)} + * and any other method returning a sub-type of {@code CoordinateReferenceSystem}. + * By contrast, if the {@code type} argument value is set to + * {@linkplain org.opengis.referencing.crs.ProjectedCRS}.class, + * then this method should return only the authority codes accepted by + * {@link org.opengis.referencing.crs.CRSAuthorityFactory#createProjectedCRS createProjectedCRS(…)}. * - * @param type the spatial reference objects type. - * @return the set of authority codes for spatial reference objects of the given type. - * If this factory does not contain any object of the given type, then this method - * returns an {@linkplain java.util.Collections#emptySet() empty set}. + * @param type the type of referencing object for which to get authority codes. + * @return the set of authority codes for referencing objects of the given type. * @throws FactoryException if access to the underlying database failed. * * @departure extension @@ -85,6 +85,25 @@ public interface AuthorityFactory extends Factory { /** * Returns a description of the object corresponding to a code. * The description may be used in graphical user interfaces. + * It may be empty if the object corresponding to the specified code has no description. + * + * @param type the type of objects for which to get a description. + * @param code value allocated by the authority for an object of the given type. + * @return a description of the object. + * @throws NoSuchAuthorityCodeException if the specified {@code code} was not found. + * @throws FactoryException if the query failed for some other reason. + * + * @since 3.1 + */ + @UML(identifier="descriptionText", obligation=OPTIONAL, specification=OGC_01009) + default Optional getDescriptionText(Class type, String code) + throws FactoryException + { + return Optional.empty(); + } + + /** + * Returns a description of the object corresponding to a code. * * @param code value allocated by authority. * @return a description of the object, or {@code null} if the object @@ -94,13 +113,10 @@ public interface AuthorityFactory extends Factory { * * @deprecated This method is ambiguous because the EPSG geodetic registry may allocate * the same code to different kinds of object. - * - * @todo Provide an alternative, maybe with a {@code Class} argument. */ @Deprecated(since = "3.1", forRemoval = true) - @UML(identifier="descriptionText", specification=OGC_01009) default InternationalString getDescriptionText(String code) throws FactoryException { - throw new UnimplementedServiceException(this, InternationalString.class, "description"); + return getDescriptionText(IdentifiedObject.class, code).orElse(null); } /** diff --git a/geoapi/src/main/java/org/opengis/referencing/IdentifiedObject.java b/geoapi/src/main/java/org/opengis/referencing/IdentifiedObject.java index 83e90ab9e..0fcf9b21a 100644 --- a/geoapi/src/main/java/org/opengis/referencing/IdentifiedObject.java +++ b/geoapi/src/main/java/org/opengis/referencing/IdentifiedObject.java @@ -37,9 +37,9 @@ * *
    *
  • A {@linkplain #getName() name} (e.g. North American Datum of 1983).
  • - *
  • Alternative names or {@linkplain #getAlias() aliases} (e.g. “NAD83” abbreviation).
  • + *
  • Alternative names or {@linkplain #getAlias() aliases} (e.g. NAD83 abbreviation).
  • *
  • {@linkplain #getIdentifiers() Identifiers} allocated by authorities - * (e.g. a register of geodetic codes and parameters might give the NAD83 datum a unique code of “6269”).
  • + * (e.g. a register of geodetic codes and parameters might give the NAD83 datum a unique code of 6269). *
  • {@linkplain #getRemarks() Remarks} about this object, including data source information.
  • *
* @@ -58,20 +58,12 @@ * The other values may or may not be set. * If the authority is EPSG, the implementer may consider using the corresponding metadata values in the EPSG tables. * - * @departure harmonization - * ISO 19111 defines two types, {@code IO_IdentifiedObjectBase} and {@code IO_IdentifiedObject}, as a - * workaround for introducing a base type for the {@code name}, {@code identifier}, {@code alias} - * and {@code remarks} properties without changing the {@code RS_ReferenceSystem} definition inherited - * from ISO 19115. Since GeoAPI replaces ISO 19115 CRS definitions by the ISO 19111 ones for providing a unified - * model, it does not need this workaround. Consequently, GeoAPI merges {@code IO_IdentifiedObjectBase} and - * {@code IO_IdentifiedObject} into this single interface. - * * @author Martin Desruisseaux (IRD) * @version 3.1 * @since 2.0 */ @Classifier(Stereotype.ABSTRACT) -@UML(identifier="IO_IdentifiedObject", specification=ISO_19111, version=2007) +@UML(identifier="IdentifiedObject", specification=ISO_19111) public interface IdentifiedObject { /** * Key for the {@value} property to be given to the diff --git a/geoapi/src/main/java/org/opengis/referencing/ObjectFactory.java b/geoapi/src/main/java/org/opengis/referencing/ObjectFactory.java index df8aa49b3..383924ad6 100644 --- a/geoapi/src/main/java/org/opengis/referencing/ObjectFactory.java +++ b/geoapi/src/main/java/org/opengis/referencing/ObjectFactory.java @@ -17,7 +17,6 @@ */ package org.opengis.referencing; -import java.util.Map; import java.util.Locale; import org.opengis.metadata.Identifier; @@ -28,7 +27,7 @@ /** - * Base interface for all factories of {@linkplain IdentifiedObject identified objects}. + * Base interface for all factories of identified objects. * Factories build up complex objects from simpler objects or values. * This factory allows applications to make * {@linkplain org.opengis.referencing.cs.CoordinateSystem coordinate systems}, @@ -38,7 +37,7 @@ * This factory is very flexible, whereas the authority factory is easier to use. * *

Object properties

- * Most factory methods expect a {@link Map Map<String,?>} argument. + * Most factory methods expect a {@code Map} argument. * The table below lists the keys that {@code ObjectFactory} implementations shall accept, * together with the type of values associated to those keys (the Alternative types column * gives examples of types that factory implementations may accept as well for convenience). diff --git a/geoapi/src/main/java/org/opengis/referencing/ReferenceSystem.java b/geoapi/src/main/java/org/opengis/referencing/ReferenceSystem.java index dae3af77c..8e3099700 100644 --- a/geoapi/src/main/java/org/opengis/referencing/ReferenceSystem.java +++ b/geoapi/src/main/java/org/opengis/referencing/ReferenceSystem.java @@ -27,7 +27,7 @@ /** - * Description of a spatial and temporal reference system used by a dataset. + * Base interface of reference systems by coordinates or by identifiers. * A reference system contains the metadata required to interpret spatial location information unambiguously. * Two methods to describe spatial location are distinguished: * diff --git a/geoapi/src/main/java/org/opengis/referencing/operation/CoordinateOperation.java b/geoapi/src/main/java/org/opengis/referencing/operation/CoordinateOperation.java index 3fd671d06..47049b99b 100644 --- a/geoapi/src/main/java/org/opengis/referencing/operation/CoordinateOperation.java +++ b/geoapi/src/main/java/org/opengis/referencing/operation/CoordinateOperation.java @@ -17,8 +17,11 @@ */ package org.opengis.referencing.operation; +import java.util.Optional; import java.util.Collection; import java.util.Collections; +import java.time.temporal.Temporal; +import org.opengis.coordinate.CoordinateSet; import org.opengis.referencing.IdentifiedObject; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.metadata.quality.PositionalAccuracy; @@ -34,8 +37,7 @@ /** - * A mathematical operation on coordinates that transforms or converts coordinates to - * another coordinate reference system. + * A mathematical operation on coordinates that transforms or converts coordinates to another CRS or epoch. * *

Inverse operation

* Many but not all coordinate operations (from @@ -51,7 +53,7 @@ * entirely different parameter values are needed, a different coordinate operation * shall be defined. * - * @author Martin Desruisseaux (IRD) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.1 * @since 1.0 * @@ -123,6 +125,32 @@ public interface CoordinateOperation extends IdentifiedObject { @UML(identifier="targetCRS", obligation=CONDITIONAL, specification=ISO_19111) CoordinateReferenceSystem getTargetCRS(); + /** + * Returns the date at which source coordinate tuples are valid. + * This is mandatory of the CRS is dynamic. + * + * @return epoch at which source coordinate tuples are valid. + * + * @since 3.1 + */ + @UML(identifier="sourceEpoch", obligation=CONDITIONAL, specification=ISO_19111) + default Optional getSourceEpoch() { + return Optional.empty(); + } + + /** + * Returns the date at which target coordinate tuples are valid. + * This is mandatory of the CRS is dynamic. + * + * @return epoch at which target coordinate tuples are valid. + * + * @since 3.1 + */ + @UML(identifier="targetEpoch", obligation=CONDITIONAL, specification=ISO_19111) + default Optional getTargetEpoch() { + return Optional.empty(); + } + /** * Version of the coordinate transformation (i.e., instantiation due to the stochastic * nature of the parameters). Mandatory when describing a transformation, and should not @@ -190,4 +218,35 @@ default InternationalString getScope() { */ @UML(identifier="CT_CoordinateTransformation.getMathTransform", specification=OGC_01009) MathTransform getMathTransform(); + + /** + * Changes coordinates from being referenced to the source CRS + * and/or epoch to being referenced to the target CRS and/or epoch. + * The CRS and epoch (if any) of the given data should (see below) be equivalent to the + * {@linkplain #getSourceCRS() source CRS} and {@linkplain #getSourceEpoch() source epoch} of this operation. + * The CRS and epoch (if any) of the returned data shall be equivalent to the + * {@linkplain #getTargetCRS() target CRS} and {@linkplain #getTargetEpoch() target epoch} of this operation. + * The order of coordinate tuples shall be preserved. + * + *

Implementation flexibility

+ * If the CRS and/or epoch of the given data are not equivalent to the source CRS + * and/or epoch of this coordinate operation, implementations can either throw an exception or automatically + * prepend an additional transform step. + * + *

Implementations are free to compute the change immediately or to delay the computation. + * For example, the changes may be computed on-the-fly in {@link CoordinateSet#stream()}.

+ * + *

This method operates on coordinate tuples and does not deal with interpolation of geometry types. + * When a coordinate set is subjected to a coordinate operation, its geometry might or might not be preserved.

+ * + * @param data the coordinates to change. + * @return the result of changing coordinates. + * @throws TransformException if some coordinates cannot be changed. + * Note that this exception not being thrown is not a guarantee that the computation + * will not fail later, for example during a stream terminal operation. + * + * @since 3.1 + */ + @UML(identifier="transform", specification=ISO_19111) + CoordinateSet transform(CoordinateSet data) throws TransformException; } diff --git a/geoapi/src/main/java/org/opengis/util/UnimplementedServiceException.java b/geoapi/src/main/java/org/opengis/util/UnimplementedServiceException.java index 10527b3be..0342b020e 100644 --- a/geoapi/src/main/java/org/opengis/util/UnimplementedServiceException.java +++ b/geoapi/src/main/java/org/opengis/util/UnimplementedServiceException.java @@ -23,8 +23,8 @@ /** * Thrown when a factory does not implement a method. * The unimplemented service may be the creation of instances of some type, - * or the parsing of texts in Well-Known Text (WKT) - * or Geographic Markup Language (GML) formats. + * or the parsing of texts in Well-Known Text (WKT) + * or Geographic Markup Language (GML) formats. * * @author Martin Desruisseaux (IRD) * @version 3.1 diff --git a/geoapi/src/main/resources/org/opengis/annotation/class-index.properties b/geoapi/src/main/resources/org/opengis/annotation/class-index.properties index 21431dbd7..f78222ab1 100644 --- a/geoapi/src/main/resources/org/opengis/annotation/class-index.properties +++ b/geoapi/src/main/resources/org/opengis/annotation/class-index.properties @@ -114,7 +114,7 @@ EX_GeographicExtent=org.opengis.metadata.extent.GeographicExtent EX_SpatialTemporalExtent=org.opengis.metadata.extent.SpatialTemporalExtent EX_TemporalExtent=org.opengis.metadata.extent.TemporalExtent EX_VerticalExtent=org.opengis.metadata.extent.VerticalExtent -IO_IdentifiedObject=org.opengis.referencing.IdentifiedObject +IdentifiedObject=org.opengis.referencing.IdentifiedObject LE_Algorithm=org.opengis.metadata.lineage.Algorithm LE_NominalResolution=org.opengis.metadata.lineage.NominalResolution LE_ProcessStep=org.opengis.metadata.lineage.ProcessStep diff --git a/geoapi/src/test/java/org/opengis/referencing/AuthorityFactoryTest.java b/geoapi/src/test/java/org/opengis/referencing/AuthorityFactoryTest.java index 4b668899e..53fdfd374 100644 --- a/geoapi/src/test/java/org/opengis/referencing/AuthorityFactoryTest.java +++ b/geoapi/src/test/java/org/opengis/referencing/AuthorityFactoryTest.java @@ -100,7 +100,9 @@ private static void verifyDefaultMethods( final Class[] epts = {String.class}; // Parameters of the methods to test. for (Method m : factoryType.getMethods()) { final String code = AuthorityFactoryMock.OBJECT_CODE; - if (m.isDefault() && Arrays.equals(epts, m.getParameterTypes())) try { + if (m.isDefault() && !m.isAnnotationPresent(Deprecated.class) + && Arrays.equals(epts, m.getParameterTypes())) try + { /* * Invoke a `createFoo(…)` method on the factory interface to test. * The method shall fail, except if it was overridden for returning From 642218e613955bfd703e328ff6a0b709cab3ccd0 Mon Sep 17 00:00:00 2001 From: Martin Desruisseaux Date: Tue, 19 Mar 2024 18:42:55 +0100 Subject: [PATCH 03/20] Partial upgrade to ISO 19111:2019 up to the `SingleCRS` interface. The `DatumEnsemble` interface is not yet added. --- .../test/referencing/CRSValidator.java | 73 ++++++++- .../python/opengis/bridge/java/referencing.py | 2 +- .../org/opengis/bridge/python/subclassed.txt | 2 +- .../opengis/annotation/ResourceBundles.java | 2 +- .../coordinate/CoordinateMetadata.java | 1 + .../org/opengis/coordinate/CoordinateSet.java | 1 + .../org/opengis/coordinate/package-info.java | 1 + .../opengis/referencing/AuthorityFactory.java | 1 + .../opengis/referencing/IdentifiedObject.java | 3 +- .../NoSuchAuthorityCodeException.java | 2 +- .../org/opengis/referencing/ObjectDomain.java | 1 + .../opengis/referencing/ObjectFactory.java | 15 +- .../opengis/referencing/ReferenceSystem.java | 5 +- .../referencing/ReferenceSystemType.java | 1 + .../referencing/crs/CRSAuthorityFactory.java | 4 +- .../opengis/referencing/crs/CRSFactory.java | 2 +- .../opengis/referencing/crs/CompoundCRS.java | 106 ++++++++---- .../crs/CoordinateReferenceSystem.java | 58 +++---- .../opengis/referencing/crs/DerivedCRS.java | 58 ++++++- .../referencing/crs/EngineeringCRS.java | 37 ++--- .../referencing/crs/GeneralDerivedCRS.java | 40 ++--- .../referencing/crs/GeocentricCRS.java | 3 +- .../opengis/referencing/crs/GeodeticCRS.java | 15 +- .../referencing/crs/GeographicCRS.java | 3 +- .../org/opengis/referencing/crs/ImageCRS.java | 4 +- .../referencing/crs/ParametricCRS.java | 3 +- .../opengis/referencing/crs/ProjectedCRS.java | 7 +- .../opengis/referencing/crs/SingleCRS.java | 43 ++--- .../opengis/referencing/crs/TemporalCRS.java | 3 +- .../opengis/referencing/crs/VerticalCRS.java | 15 +- .../opengis/referencing/crs/package-info.java | 51 +++--- .../org/opengis/referencing/datum/Datum.java | 9 +- .../datum/DatumAuthorityFactory.java | 4 +- .../referencing/datum/DatumFactory.java | 4 +- .../opengis/referencing/datum/Ellipsoid.java | 3 +- .../referencing/datum/EngineeringDatum.java | 22 ++- .../referencing/datum/GeodeticDatum.java | 35 +++- .../opengis/referencing/datum/ImageDatum.java | 32 +++- .../referencing/datum/ParametricDatum.java | 1 + .../referencing/datum/PixelInCell.java | 9 +- .../referencing/datum/PrimeMeridian.java | 3 +- .../referencing/datum/TemporalDatum.java | 3 +- .../referencing/datum/VerticalDatum.java | 13 +- .../referencing/datum/VerticalDatumType.java | 77 ++++++--- .../referencing/datum/package-info.java | 155 ++---------------- .../referencing/operation/Conversion.java | 4 +- .../operation/CoordinateOperation.java | 4 +- .../CoordinateOperationAuthorityFactory.java | 4 +- .../referencing/operation/package-info.java | 2 +- .../org/opengis/referencing/package-info.java | 1 + .../main/python/opengis/referencing/crs.py | 11 +- .../python/opengis/referencing/operation.py | 8 +- .../opengis/annotation/class-index.properties | 4 +- .../java/org/opengis/geoapi/NameSpaces.java | 3 +- .../opengis/geoapi/MethodSignatureTest.java | 9 +- .../referencing/crs/CompoundCRSMock.java | 9 +- .../referencing/crs/CompoundCRSTest.java | 27 ++- src/main/metanorma/code/java/annotation.adoc | 2 +- 58 files changed, 551 insertions(+), 469 deletions(-) diff --git a/geoapi-conformance/src/main/java/org/opengis/test/referencing/CRSValidator.java b/geoapi-conformance/src/main/java/org/opengis/test/referencing/CRSValidator.java index 43b8e07ff..b2d34fd62 100644 --- a/geoapi-conformance/src/main/java/org/opengis/test/referencing/CRSValidator.java +++ b/geoapi-conformance/src/main/java/org/opengis/test/referencing/CRSValidator.java @@ -21,6 +21,7 @@ import java.util.List; import java.util.ArrayList; import java.util.LinkedHashSet; +import java.util.function.Supplier; import org.opengis.referencing.cs.*; import org.opengis.referencing.crs.*; @@ -63,8 +64,8 @@ public class CRSValidator extends ReferencingValidator { */ /** - * {@code true} if validation of the conversion by {@link #validateGeneralDerivedCRS} - * is under way. Used in order to avoid never-ending recursivity. + * {@code true} if validation of the conversion by {@link #validateGeneralDerivedCRS} is under way. + * Used in order to avoid never-ending recursivity. * * @todo Replace by a more general mechanism straight in {@link ValidatorContainer}. */ @@ -269,7 +270,7 @@ public void validate(final DerivedCRS object) { * * @param object the object to validate, or {@code null}. */ - private void validateGeneralDerivedCRS(final GeneralDerivedCRS object) { + private void validateGeneralDerivedCRS(final DerivedCRS object) { if (!Boolean.TRUE.equals(VALIDATING.get())) try { VALIDATING.set(Boolean.TRUE); final Conversion conversion = object.getConversionFromBase(); @@ -280,11 +281,11 @@ private void validateGeneralDerivedCRS(final GeneralDerivedCRS object) { final CoordinateReferenceSystem targetCRS = conversion.getTargetCRS(); if (baseCRS != null && sourceCRS != null) { assertSame(baseCRS, sourceCRS, - "GeneralDerivedCRS: The base CRS should be the source CRS of the conversion."); + "DerivedCRS: The base CRS should be the source CRS of the conversion."); } if (targetCRS != null) { assertSame(object, targetCRS, - "GeneralDerivedCRS: The derived CRS should be the target CRS of the conversion."); + "DerivedCRS: The derived CRS should be the target CRS of the conversion."); } } } finally { @@ -400,16 +401,76 @@ public void validate(final CompoundCRS object) { final CoordinateSystem cs = object.getCoordinateSystem(); mandatory("CompoundCRS: shall have a CoordinateSystem.", cs); container.validate(cs); - + AxisDirection[] directions = null; + if (cs != null) { + directions = new AxisDirection[cs.getDimension()]; + for (int i=0; i components = object.getComponents(); mandatory("CompoundCRS: shall have components.", components); if (components != null) { + int dimension = 0; // If the above 'mandatory(…)' call accepted an empty list, we accept it too. assertNotEquals(1, components.size(), "CompoundCRS: shall have at least 2 components."); for (final CoordinateReferenceSystem component : components) { dispatch(component); + dimension = compareAxes(component.getCoordinateSystem(), directions, dimension); + } + if (directions != null) { + assertEquals(directions.length, dimension, "CompoundCRS: unexpected sum of the dimension of components."); + } + } + /* + * Verify the components again, but without nested compound CRS. + */ + final List singles = object.getSingleComponents(); + mandatory("CompoundCRS: shall have components.", singles); + if (singles != null) { + int dimension = 0; + assertNotEquals(1, singles.size(), "CompoundCRS: shall have at least 2 components."); + for (final SingleCRS component : singles) { + dispatch(component); + dimension = compareAxes(component.getCoordinateSystem(), directions, dimension); + } + if (directions != null) { + assertEquals(directions.length, dimension, "CompoundCRS: unexpected sum of the dimension of components."); + } + } + } + + /** + * Checks if the axis directions of the given coordinate system are the expected one. + * + * @param cs the coordinate system to validate, or {@code null} if none. + * @param directions the expected directions, or {@code null} if unknown. + * @param index index of the first element in the {@code directions} array. + * @return index after the last element in the {@code directions} array. + */ + private static int compareAxes(final CoordinateSystem cs, final AxisDirection[] directions, int index) { + if (directions != null) { + assertNotNull("CompoundCRS: missing coordinate system for component."); + final int dimension = cs.getDimension(); + assertTrue(index + dimension < directions.length, "CompoundCRS: components have too many dimensions."); + for (int i=0; i message = () -> "CompoundCRS: inconsistent axis at dimension " + d + "."; + final CoordinateSystemAxis axis = cs.getAxis(d); + assertNotNull(axis, message); + assertEquals(expected, axis.getDirection(), message); + } } } + return index; } /** diff --git a/geoapi-java-python/src/main/python/opengis/bridge/java/referencing.py b/geoapi-java-python/src/main/python/opengis/bridge/java/referencing.py index e21992ff8..0ae6815f5 100644 --- a/geoapi-java-python/src/main/python/opengis/bridge/java/referencing.py +++ b/geoapi-java-python/src/main/python/opengis/bridge/java/referencing.py @@ -111,7 +111,7 @@ def __init__(self, proxy): -class ProjectedCRS(IdentifiedObject, opengis.referencing.crs.GeneralDerivedCRS): +class ProjectedCRS(IdentifiedObject, opengis.referencing.crs.DerivedCRS): def __init__(self, proxy): super().__init__(proxy) diff --git a/geoapi-java-python/src/main/resources/org/opengis/bridge/python/subclassed.txt b/geoapi-java-python/src/main/resources/org/opengis/bridge/python/subclassed.txt index f4bb5fc96..40444e648 100644 --- a/geoapi-java-python/src/main/resources/org/opengis/bridge/python/subclassed.txt +++ b/geoapi-java-python/src/main/resources/org/opengis/bridge/python/subclassed.txt @@ -24,7 +24,7 @@ org.opengis.parameter.GeneralParameterValue org.opengis.referencing.IdentifiedObject org.opengis.referencing.ReferenceSystem org.opengis.referencing.crs.CoordinateReferenceSystem -org.opengis.referencing.crs.GeneralDerivedCRS +org.opengis.referencing.crs.DerivedCRS org.opengis.referencing.crs.GeodeticCRS org.opengis.referencing.crs.SingleCRS org.opengis.referencing.cs.AffineCS diff --git a/geoapi/src/main/java/org/opengis/annotation/ResourceBundles.java b/geoapi/src/main/java/org/opengis/annotation/ResourceBundles.java index d7e12615c..72abc1c2f 100644 --- a/geoapi/src/main/java/org/opengis/annotation/ResourceBundles.java +++ b/geoapi/src/main/java/org/opengis/annotation/ResourceBundles.java @@ -119,7 +119,7 @@ public static ResourceBundle descriptions(final Locale locale) { * The returned map is the converse of {@link UML#identifier()}. * *

Examples

- * {@code classIndex.getString("SC_CRS")} returns + * {@code classIndex.getString("CRS")} returns * {@code "org.opengis.referencing.crs.CoordinateReferenceSystem"}. * *

Performance note

diff --git a/geoapi/src/main/java/org/opengis/coordinate/CoordinateMetadata.java b/geoapi/src/main/java/org/opengis/coordinate/CoordinateMetadata.java index 2820478ca..713a87563 100644 --- a/geoapi/src/main/java/org/opengis/coordinate/CoordinateMetadata.java +++ b/geoapi/src/main/java/org/opengis/coordinate/CoordinateMetadata.java @@ -32,6 +32,7 @@ * If the CRS is dynamic, then a coordinate epoch is also mandatory. * Whether the CRS is dynamic is determined through the CRS's reference frame definition. * + * @author OGC Topic 2 (for abstract model and documentation) * @author Martin Desruisseaux (Geomatys) * @version 3.1 * @since 3.1 diff --git a/geoapi/src/main/java/org/opengis/coordinate/CoordinateSet.java b/geoapi/src/main/java/org/opengis/coordinate/CoordinateSet.java index f34891b50..0c3a26182 100644 --- a/geoapi/src/main/java/org/opengis/coordinate/CoordinateSet.java +++ b/geoapi/src/main/java/org/opengis/coordinate/CoordinateSet.java @@ -39,6 +39,7 @@ * If the CRS is dynamic, the {@code CoordinateSet} may be converted to another coordinate epoch * through a point motion coordinate operation that includes time evolution. * + * @author OGC Topic 2 (for abstract model and documentation) * @author Martin Desruisseaux (Geomatys) * @version 3.1 * diff --git a/geoapi/src/main/java/org/opengis/coordinate/package-info.java b/geoapi/src/main/java/org/opengis/coordinate/package-info.java index e2a64817c..c54fa53f7 100644 --- a/geoapi/src/main/java/org/opengis/coordinate/package-info.java +++ b/geoapi/src/main/java/org/opengis/coordinate/package-info.java @@ -30,6 +30,7 @@ *

Coordinate tuples can be represented by instances of {@link org.opengis.geometry.DirectPosition} * or by plain Java arrays of numbers.

* + * @author OGC Topic 2 (for abstract model and documentation) * @author Martin Desruisseaux (Geomatys) * @version 3.1 * @since 3.1 diff --git a/geoapi/src/main/java/org/opengis/referencing/AuthorityFactory.java b/geoapi/src/main/java/org/opengis/referencing/AuthorityFactory.java index c45fa49cb..e10be77bb 100644 --- a/geoapi/src/main/java/org/opengis/referencing/AuthorityFactory.java +++ b/geoapi/src/main/java/org/opengis/referencing/AuthorityFactory.java @@ -39,6 +39,7 @@ * of coordinate reference systems, and other spatial referencing objects, where each object has a code number ID. * For example, the EPSG code for a WGS84 Lat/Lon CRS is 4326.

* + * @author OGC Topic 2 (for abstract model and documentation) * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.1 * @since 1.0 diff --git a/geoapi/src/main/java/org/opengis/referencing/IdentifiedObject.java b/geoapi/src/main/java/org/opengis/referencing/IdentifiedObject.java index 0fcf9b21a..edb2f286a 100644 --- a/geoapi/src/main/java/org/opengis/referencing/IdentifiedObject.java +++ b/geoapi/src/main/java/org/opengis/referencing/IdentifiedObject.java @@ -58,7 +58,8 @@ * The other values may or may not be set. * If the authority is EPSG, the implementer may consider using the corresponding metadata values in the EPSG tables. * - * @author Martin Desruisseaux (IRD) + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.1 * @since 2.0 */ diff --git a/geoapi/src/main/java/org/opengis/referencing/NoSuchAuthorityCodeException.java b/geoapi/src/main/java/org/opengis/referencing/NoSuchAuthorityCodeException.java index b46d2b385..8224017d3 100644 --- a/geoapi/src/main/java/org/opengis/referencing/NoSuchAuthorityCodeException.java +++ b/geoapi/src/main/java/org/opengis/referencing/NoSuchAuthorityCodeException.java @@ -25,7 +25,7 @@ * This is a specialization of {@link NoSuchIdentifierException} with the identifier separated in its authority * and code components. * - * @author Martin Desruisseaux (IRD) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.1 * @since 1.0 * diff --git a/geoapi/src/main/java/org/opengis/referencing/ObjectDomain.java b/geoapi/src/main/java/org/opengis/referencing/ObjectDomain.java index 5aa69eb50..ae86a4367 100644 --- a/geoapi/src/main/java/org/opengis/referencing/ObjectDomain.java +++ b/geoapi/src/main/java/org/opengis/referencing/ObjectDomain.java @@ -31,6 +31,7 @@ * datum or coordinate system is applied. The domain of validity describes the spatial and * temporal extent in which the object can be used. * + * @author OGC Topic 2 (for abstract model and documentation) * @author Martin Desruisseaux (Geomatys) * @version 3.1 * @since 3.1 diff --git a/geoapi/src/main/java/org/opengis/referencing/ObjectFactory.java b/geoapi/src/main/java/org/opengis/referencing/ObjectFactory.java index 383924ad6..365d33dce 100644 --- a/geoapi/src/main/java/org/opengis/referencing/ObjectFactory.java +++ b/geoapi/src/main/java/org/opengis/referencing/ObjectFactory.java @@ -51,32 +51,27 @@ * Value type * Alternative types * Value returned by - * - * + * * {@value org.opengis.referencing.IdentifiedObject#NAME_KEY} * {@link Identifier} * {@link String} (see alternatives below) * {@link IdentifiedObject#getName()} - * - * + * * {@value org.opengis.referencing.IdentifiedObject#ALIAS_KEY} * {@linkplain GenericName}[] * {@link GenericName}, {@link String} or {@linkplain String}[] * {@link IdentifiedObject#getAlias()} - * - * + * * {@value org.opengis.referencing.IdentifiedObject#IDENTIFIERS_KEY} * {@linkplain Identifier}[] * {@link Identifier} * {@link IdentifiedObject#getIdentifiers()} - * - * + * * {@value org.opengis.referencing.IdentifiedObject#DOMAINS_KEY} * {@linkplain ObjectDomain}[] * {@link ObjectDomain} * {@link IdentifiedObject#getDomains()} - * - * + * * {@value org.opengis.referencing.IdentifiedObject#REMARKS_KEY} * {@link InternationalString} * {@link String} (see localization below) diff --git a/geoapi/src/main/java/org/opengis/referencing/ReferenceSystem.java b/geoapi/src/main/java/org/opengis/referencing/ReferenceSystem.java index 8e3099700..376a85700 100644 --- a/geoapi/src/main/java/org/opengis/referencing/ReferenceSystem.java +++ b/geoapi/src/main/java/org/opengis/referencing/ReferenceSystem.java @@ -63,7 +63,8 @@ * ISO 19115:2003 {@code RS_ReferenceSystem} than to * ISO 19115:2015 {@code MD_ReferenceSystem}. * - * @author Martin Desruisseaux (IRD) + * @author ISO 19115 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.1 * @since 1.0 * @@ -101,7 +102,7 @@ public interface ReferenceSystem extends IdentifiedObject { * @deprecated Replaced by {@link #getDomains()} as of ISO 19111:2019. */ @Deprecated(since="3.1", forRemoval=true) - @UML(identifier="domainOfValidity", obligation=OPTIONAL, specification=ISO_19111, version=2007) + @UML(identifier="SC_CRS.domainOfValidity", obligation=OPTIONAL, specification=ISO_19111, version=2007) default Extent getDomainOfValidity() { return Legacy.getDomainOfValidity(getDomains()); } diff --git a/geoapi/src/main/java/org/opengis/referencing/ReferenceSystemType.java b/geoapi/src/main/java/org/opengis/referencing/ReferenceSystemType.java index 05a8f56fc..30b8693c0 100644 --- a/geoapi/src/main/java/org/opengis/referencing/ReferenceSystemType.java +++ b/geoapi/src/main/java/org/opengis/referencing/ReferenceSystemType.java @@ -28,6 +28,7 @@ /** * Defines type of reference system used. * + * @author ISO 19115 (for abstract model and documentation) * @author Rémi Maréchal (Geomatys) * @version 3.1 * @since 3.1 diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/CRSAuthorityFactory.java b/geoapi/src/main/java/org/opengis/referencing/crs/CRSAuthorityFactory.java index ced21b12b..af7a8271b 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/CRSAuthorityFactory.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/CRSAuthorityFactory.java @@ -28,7 +28,7 @@ /** - * Creates {@linkplain CoordinateReferenceSystem coordinate reference systems} using authority codes. + * Creates coordinate reference systems using authority codes. * External authorities are used to manage definitions of objects used in this interface. * The definitions of these objects are referenced using code strings. * A commonly used authority is EPSG. @@ -43,7 +43,7 @@ * saying that the type or service is not supported. * * - * @author Martin Desruisseaux (IRD) + * @author Martin Desruisseaux (IRD, Geomatys) * @author Johann Sorel (Geomatys) * @version 3.1 * @since 1.0 diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/CRSFactory.java b/geoapi/src/main/java/org/opengis/referencing/crs/CRSFactory.java index e76cacd1a..7b92b98fa 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/CRSFactory.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/CRSFactory.java @@ -51,7 +51,7 @@ * the default is to throw an {@link UnimplementedServiceException} * with a message saying that the type or service is not supported. * - * @author Martin Desruisseaux (IRD) + * @author Martin Desruisseaux (IRD, Geomatys) * @author Johann Sorel (Geomatys) * @version 3.1 * @since 1.0 diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/CompoundCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/CompoundCRS.java index a96bb511f..dfd0a8983 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/CompoundCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/CompoundCRS.java @@ -19,6 +19,9 @@ import java.util.Map; import java.util.List; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Collections; import org.opengis.referencing.cs.CoordinateSystem; import org.opengis.annotation.UML; @@ -28,32 +31,25 @@ /** * A CRS describing the position of points through two or more independent CRSs. - * Thus it is indirectly associated with two or more - * {@linkplain org.opengis.referencing.cs.CoordinateSystem coordinate systems} - * and {@linkplain org.opengis.referencing.datum.Datum datums} by defining the compound - * CRS as an ordered set of two or more instances of {@link CoordinateReferenceSystem}. - * - *

For spatial coordinates, a number of constraints exist for the construction of Compound CRSs. - * For example, the coordinate reference systems that are combined should not contain any duplicate - * or redundant axes. Valid combinations include:

+ * For spatial coordinates, a number of constraints exist for the construction of Compound CRSs. + * For example, the CRSs that are combined should not contain any duplicate or redundant axes. + * Valid combinations include (non-exhaustive list): * *
    *
  • Geographic 2D + Vertical
  • *
  • Geographic 2D + Engineering 1D (near vertical)
  • - *
  • Projected + Vertical
  • - *
  • Projected + Engineering 1D (near vertical)
  • - *
  • Engineering (horizontal 2D or 1D linear) + Vertical
  • + *
  • Projected 2D + Vertical
  • + *
  • Projected 2D + Engineering 1D (near vertical)
  • + *
  • Engineering (horizontal 2D) + Vertical
  • *
  • Engineering (1D linear) + Vertical
  • *
* - * Any coordinate reference system, or any of the above listed combinations of coordinate reference systems, - * can have a {@link TemporalCRS} added. More than one temporal CRS may be added if these axes represent - * different time quantities. For example, the oil industry sometimes uses "4D seismic", by which is meant - * seismic data with the vertical axis expressed in milliseconds (signal travel time). A second time axis - * indicates how it changes with time (years), e.g. as a reservoir is gradually exhausted of its recoverable - * oil or gas. + * Any coordinate reference system (CRS), or any of the above listed combinations of CRSs, + * can have a {@link TemporalCRS} added. More than one temporal CRS may be added if these axes represent + * different time quantities. * - * @author Martin Desruisseaux (IRD) + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.1 * @since 1.0 * @@ -63,34 +59,80 @@ @UML(identifier="SC_CompoundCRS", specification=ISO_19111, version=2007) public interface CompoundCRS extends CoordinateReferenceSystem { /** - * The ordered list of coordinate reference systems. + * Returns the ordered list of CRS components. + * The returned list may contain nested compound CRS. + * For a list without nesting, as required by ISO 19111, see {@link #getSingleComponents()}. + * + *

Why nested compound CRS

+ * The use of nested compound CRSs can avoid metadata lost when a temporal CRS + * is appended to spatial components defined in a preexisting compound CRS. + * A three-dimensional compound CRS has its own metadata (e.g., an EPSG code) + * that may not be found in the individual horizontal and vertical components. + * A flatten list of horizontal, vertical and temporal components would lost those metadata. + * In particular, the lost of authority code reduces the scope of the + * {@linkplain org.opengis.referencing.operation.CoordinateOperationAuthorityFactory#createFromCoordinateReferenceSystemCodes + * search for coordinate operations} that an application can do. * - * @return the ordered list of coordinate reference systems. + * @return the ordered list of components of this compound CRS. * * @departure generalization - * ISO 19111 said nesting of compound CRSs shall not be permitted; the individual single systems - * shall be aggregated together. However, this approach causes data lost: it is difficult to add - * a temporal CRS to an existing three-dimensional compound CRS without loosing the name and identifiers - * of the 3D CRS, unless nesting is permitted. It is programmatically easier to convert nested CRSs to a - * flat list of single CRSs when needed than to reconstruct the 3D CRS from the single components. - * Consequently, GeoAPI has been keep conformant with the legacy OGC 01-009 specification in this aspect, - * which were allowing nested compound CRS. + * Added as an alternative to the association defined by ISO 19111 for resolving the problem of metadata lost. + * The ISO 19111 requirement is still available as the {@link #getSingleComponents()} method. */ - @UML(identifier="componentReferenceSystem", obligation=MANDATORY, specification=ISO_19111) List getComponents(); + /** + * Returns the ordered list of CRS components, none of which itself compound. + * If this compound CRS contains nested compound CRS components, + * then those components are flattened recursively in a sequence of {@link SingleCRS} objects. + * + * @return the ordered list of components of this compound CRS, none of which itself compound. + * + * @since 3.1 + */ + @UML(identifier="componentReferenceSystem", obligation=MANDATORY, specification=ISO_19111) + default List getSingleComponents() { + var singles = new ArrayList(5); + flatten(singles, new LinkedList<>()); // Linked list is cheap to construct and efficient with 0 or 1 element. + return Collections.unmodifiableList(singles); + } + + /** + * Appends recursively all single components in the given list. + * + * @param singles the list where to add single components. + * @param safety a safety against infinite recursive method calls. + * @throws IllegalStateException if recursive components are detected. + */ + private void flatten(final List singles, final List safety) { + for (CoordinateReferenceSystem crs : getComponents()) { + if (crs instanceof SingleCRS) { + singles.add((SingleCRS) crs); + } else if (crs instanceof CompoundCRS) { + for (Object previous : safety) { + if (previous == this) { + throw new IllegalStateException("Recursive components detected."); + } + } + safety.add(this); + ((CompoundCRS) crs).flatten(singles, safety); + } + } + } + /** * Returns a view over all coordinate systems of this compound CRS. * The returned coordinate system shall have a {@linkplain CoordinateSystem#getDimension() dimension} * equals to the sum of the dimensions of all {@linkplain #getComponents() components}, - * and axes obtained from the coordinate system of each component. + * and axes obtained from the coordinate system of each component in the same order. * * @return view over all coordinate systems of this compound CRS. * * @departure generalization - * ISO 19111 defines this method for {@code SC_SingleCRS} only. GeoAPI declares this method in - * {@code CompoundCRS} as well for user convenience, because CS dimension and axes are commonly - * requested information that are still available (indirectly) for compound CRS. + * ISO 19111 defines this method for {@link SingleCRS} only. + * GeoAPI declares this method in {@code CompoundCRS} as well for user convenience, + * because CS dimension and axes are commonly requested information + * that are still available (indirectly) for compound CRS. */ @Override default CoordinateSystem getCoordinateSystem() { diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/CoordinateReferenceSystem.java b/geoapi/src/main/java/org/opengis/referencing/crs/CoordinateReferenceSystem.java index 611f92a36..1e4ba9713 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/CoordinateReferenceSystem.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/CoordinateReferenceSystem.java @@ -27,63 +27,57 @@ /** - * Base type of all Coordinate Reference Systems (CRS). + * Base type of all Coordinate Reference Systems (CRS). * This is the base interface for two cases: * *
    *
  • {@link SingleCRS}, defined by a * {@linkplain org.opengis.referencing.cs.CoordinateSystem coordinate system} and a - * {@linkplain org.opengis.referencing.datum.Datum datum};
  • + * {@linkplain org.opengis.referencing.datum.Datum datum} or datum ensemble; *
  • {@link CompoundCRS}, defined as a sequence of {@code SingleCRS}.
  • *
* *

Purpose

- * A coordinate reference system (CRS) captures the choice of values for the parameters that constitute - * the degrees of freedom of the coordinate space. The fact that such a choice has to be made, - * either arbitrarily or by adopting values from survey measurements, leads to the large number - * of coordinate reference systems in use around the world. It is also the cause of the little - * understood fact that the latitude and longitude of a point are not unique. Without the full - * specification of the coordinate reference system, coordinates are ambiguous at best and - * meaningless at worst. + * A coordinate reference system (CRS) captures the choice of values + * for the parameters that constitute the degrees of freedom of the coordinate space. + * The fact that such a choice has to be made, either arbitrarily or by adopting values from survey measurements, + * leads to the large number of coordinate reference systems in use around the world. + * It is also the cause of the little understood fact that the latitude and longitude of a point are not unique. + * Without the full specification of the coordinate reference system, + * coordinates are ambiguous at best and meaningless at worst. * - *

Spatio-temporal CRS

+ *

Spatiotemporal CRS

* The concept of coordinates may be expanded from a strictly spatial context to include time. * Time is then added as another coordinate to the coordinate tuple. It is even possible to add * two time-coordinates, provided the two coordinates describe different independent quantities. * An example of the latter is the time/space position of a subsurface point of which the vertical * coordinate is expressed as the two-way travel time of a sound signal in milliseconds, as is - * common in seismic imaging. A second time-coordinate indicates the time of observation, usually - * expressed in whole years. + * common in seismic imaging. A second time-coordinate indicates the time of observation. * - * @author Martin Desruisseaux (IRD) - * @version 3.0 + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) + * @version 3.1 * @since 1.0 */ @Classifier(Stereotype.ABSTRACT) -@UML(identifier="SC_CRS", specification=ISO_19111, version=2007) +@UML(identifier="CRS", specification=ISO_19111) public interface CoordinateReferenceSystem extends ReferenceSystem { /** - * Returns the coordinate system of a single CRS, or a view over all coordinate systems of a compound CRS. - * More specifically: + * Returns the coordinate axes with specified units of measure. + * The type of the returned coordinate system should be one of the sub-interfaces defined in + * the {@link org.opengis.referencing.cs} package. The subtype implies the mathematical rules that define + * how coordinate values are calculated from distances, angles and other geometric elements and vice versa. * - *
    - *
  • If the CRS instance on which this method is invoked is an instance of the - * {@link SingleCRS} interface, then the CS instance which is returned shall - * be one of the defined sub-interfaces of {@link CoordinateSystem}.
  • + *

    An exception to above recommendation is when this CRS is an instance of {@link CompoundCRS}. + * In that case, the coordinate system type may be hidden and the implied mathematical rules are unspecified. + * However the coordinate system object is still useful as a list of axes.

    * - *
  • If the CRS instance on which this method is invoked is an instance of the - * {@link CompoundCRS} interface, then the CS instance which is returned shall - * have a {@linkplain CoordinateSystem#getDimension() dimension} equals to the - * sum of the dimensions of all {@linkplain CompoundCRS#getComponents() components}, - * and axes obtained from the coordinate system of each component.
  • - *
- * - * @return the coordinate system. + * @return the coordinate axes with specified units of measure. * * @departure generalization - * ISO 19111 defines this method for {@code SC_SingleCRS} only. GeoAPI declares this method in - * this parent interface for user convenience, since CS dimension and axes are commonly requested - * information and will always be available, directly or indirectly, even for {@code SC_CompoundCRS}. + * ISO 19111 defines this method for {@link SingleCRS} only. GeoAPI declares this method in this parent interface + * for user convenience, because CRS dimension and axes are commonly requested information and are + * always available, directly or indirectly, even for {@link CompoundCRS}. */ CoordinateSystem getCoordinateSystem(); } diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/DerivedCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/DerivedCRS.java index c1afb1473..5022a63c4 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/DerivedCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/DerivedCRS.java @@ -18,29 +18,36 @@ package org.opengis.referencing.crs; import java.util.Map; +import org.opengis.referencing.datum.Datum; import org.opengis.referencing.cs.CoordinateSystem; import org.opengis.referencing.operation.Conversion; import org.opengis.annotation.UML; + +import static org.opengis.annotation.Obligation.MANDATORY; import static org.opengis.annotation.Specification.*; /** - * A coordinate reference system that is defined by its coordinate conversion from another CRS - * but is not a projected CRS. - * This category includes coordinate reference systems derived from a projected CRS. - * - *

A {@code DerivedCRS} instance may also implement one of the interfaces listed below, - * provided that the conditions in the right column are meet:

+ * A CRS that is defined by applying a coordinate conversion to another preexisting CRS. + * The derived CRS inherits its datum (reference frame) or datum ensemble from its base CRS. + * A {@code DerivedCRS} instance may also implement one of the interfaces listed below, + * provided that the conditions in the right column are met: * * * * + * * * * * *
Derived CRS types
Type Conditions
{@link ProjectedCRS} Base CRS is a {@link GeographicCRS} and conversion is a map projection.
{@link GeodeticCRS} Base CRS is also a {@code GeodeticCRS}.
{@link VerticalCRS} Base CRS is also a {@code VerticalCRS}.
{@link TemporalCRS} Base CRS is also a {@code TemporalCRS}.
{@link EngineeringCRS} Base CRS is a {@code GeodeticCRS}, {@code ProjectedCRS} or {@code EngineeringCRS}.
* + * In the special case where the CRS is derived from a base {@link GeographicCRS} by applying + * a coordinate conversion known as a map projection to latitude and longitude ellipsoidal coordinate values, + * the {@link ProjectedCRS} subtype should be used. Projected CRSs are modeled as a special case + * of derived CRS because of their importance in geographic information. + * * @departure integration * ISO 19111 defines a {@code SC_DerivedCRSType} code list with the following values: * {@code geodetic}, {@code vertical}, {@code engineering} and {@code image}. @@ -53,13 +60,48 @@ * than the code list with more flexibility. For example, it allows to use a derived CRS of type “vertical” * with API expecting an instance of {@code VerticalCRS}. * - * @author Martin Desruisseaux (IRD) - * @version 3.0 + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) + * @version 4.0 * @since 1.0 * * @see CRSAuthorityFactory#createDerivedCRS(String) * @see CRSFactory#createDerivedCRS(Map, CoordinateReferenceSystem, Conversion, CoordinateSystem) */ +@SuppressWarnings("removal") @UML(identifier="SC_DerivedCRS", specification=ISO_19111, version=2007) public interface DerivedCRS extends GeneralDerivedCRS { + /** + * Returns the base coordinate reference system. + * + * @return the base coordinate reference system. + */ + @Override + @UML(identifier="baseCRS", obligation=MANDATORY, specification=ISO_19111) + SingleCRS getBaseCRS(); + + /** + * Returns the conversion from the base CRS to this CRS. + * + * @return the conversion from the base CRS. + * + * @departure rename + * "{@code conversion}" may be confusing as a method name + * since it does not indicate which CRS is the source or which is the target. + * The OGC 01-009 specification used the {@code toBase()} method name. + * By analogy with 01-009, GeoAPI defines a method name which contains the "{@code FromBase}" expression. + */ + @Override + @UML(identifier="conversion", obligation=MANDATORY, specification=ISO_19111) + Conversion getConversionFromBase(); + + /** + * Returns the same datum as the base CRS datum. + * + * @return the datum of this derived CRS, which is the {@linkplain #getBaseCRS() base CRS} datum. + */ + @Override + default Datum getDatum() { + return getBaseCRS().getDatum(); + } } diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/EngineeringCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/EngineeringCRS.java index e184e4dcb..8fd3e6974 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/EngineeringCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/EngineeringCRS.java @@ -27,32 +27,24 @@ /** - * A 1-, 2- or 3-dimensional contextually local CRS. - * It can be divided into two broad categories: + * A 1-, 2- or 3-dimensional CRS used locally. + * It can be divided into three broad categories: * *
    - *
  • earth-fixed systems applied to engineering activities on or near the surface of the earth;
  • - *
  • CRSs on moving platforms such as road vehicles, vessels, aircraft, or spacecraft.
  • + *
  • planet-fixed systems applied to engineering activities on or near the surface of the planet;
  • + *
  • CRSs on moving platforms such as road vehicles, vessels, aircraft, or spacecraft.
  • + *
  • CRSs used to describe spatial location internally on an image.
  • *
* - * Earth-fixed Engineering CRSs are commonly based on a simple flat-earth approximation of the - * earth's surface, and the effect of earth curvature on feature geometry is ignored: calculations - * on coordinates use simple plane arithmetic without any corrections for earth curvature. The - * application of such Engineering CRSs to relatively small areas and "contextually local" is in - * this case equivalent to "spatially local". + *

Planet-fixed engineering CRSs are commonly based on a simple flat-earth approximation + * of the planet's surface, and the effect of planet curvature on feature geometry is ignored: + * calculations on coordinates use simple plane arithmetic without any corrections for planet curvature.

* - *

Engineering CRSs used on moving platforms are usually intermediate coordinate reference - * systems that are computationally required to calculate coordinates referenced to - * {@linkplain GeocentricCRS geocentric}, {@linkplain GeographicCRS geographic} or - * {@linkplain ProjectedCRS projected} CRSs. These engineering coordinate reference - * systems are subject to all the motions of the platform with which they are associated. - * In this case "contextually local" means that the associated coordinates are meaningful - * only relative to the moving platform. Earth curvature is usually irrelevant and is therefore - * ignored. In the spatial sense their applicability may extend from the immediate vicinity of - * the platform (e.g. a moving seismic ship) to the entire earth (e.g. in space applications). - * The determining factor is the mathematical model deployed in the positioning calculations. - * Transformation of coordinates from these moving Engineering CRSs to earth-referenced coordinate - * reference systems involves time-dependent coordinate operation parameters.

+ *

Engineering CRSs used on moving platforms + * are subject to all the motions of the platform with which they are associated. + * In this case the associated coordinates are meaningful only relative to the moving platform. + * Transformation of coordinates from these moving engineering CRSs to planet-referenced + * CRSs involves time-dependent coordinate operation parameters.

* *

This type of CRS can be used with coordinate systems of type * {@link org.opengis.referencing.cs.AffineCS}, @@ -63,7 +55,8 @@ * {@link org.opengis.referencing.cs.SphericalCS}, * {@link org.opengis.referencing.cs.UserDefinedCS}.

* - * @author Martin Desruisseaux (IRD) + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.0 * @since 1.0 * diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/GeneralDerivedCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/GeneralDerivedCRS.java index ecc743b1b..fa7f61a00 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/GeneralDerivedCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/GeneralDerivedCRS.java @@ -17,7 +17,6 @@ */ package org.opengis.referencing.crs; -import org.opengis.referencing.datum.Datum; import org.opengis.referencing.operation.Conversion; import org.opengis.annotation.UML; import org.opengis.annotation.Classifier; @@ -28,19 +27,16 @@ /** - * A coordinate reference system that is defined by its coordinate conversion from another coordinate reference system. - * Derived CRS are not directly associated to a {@linkplain org.opengis.referencing.datum.Datum datum}. + * A CRS that is defined by applying a coordinate conversion to another preexisting CRS. + * The derived CRS inherits its datum (reference frame) or datum ensemble from its base CRS. * - *

In principle, all sub-types of {@link CoordinateReferenceSystem} may take on the role of either source or - * derived CRS with the exception of a {@link GeocentricCRS} and a {@link ProjectedCRS}. The latter is modelled - * as an object class under its own name, rather than as a general derived CRS of type "projected". - * This has been done to honour common practice, which acknowledges projected CRSs as one of the best known - * types of coordinate reference systems.

- * - * @author Martin Desruisseaux (IRD) - * @version 4.0 + * @author Martin Desruisseaux (IRD, Geomatys) + * @version 3.1 * @since 1.0 + * + * @deprecated As of ISO 19111:2019, this interface is renamed as {@link DerivedCRS}. */ +@Deprecated(since="3.1", forRemoval=true) @Classifier(Stereotype.ABSTRACT) @UML(identifier="SC_GeneralDerivedCRS", specification=ISO_19111, version=2007) public interface GeneralDerivedCRS extends SingleCRS { @@ -49,30 +45,14 @@ public interface GeneralDerivedCRS extends SingleCRS { * * @return the base coordinate reference system. */ - @UML(identifier="baseCRS", obligation=MANDATORY, specification=ISO_19111) - SingleCRS getBaseCRS(); + @UML(identifier="baseCRS", obligation=MANDATORY, specification=ISO_19111, version=2007) + CoordinateReferenceSystem getBaseCRS(); /** * Returns the conversion from the {@linkplain #getBaseCRS() base CRS} to this CRS. * * @return the conversion from the base CRS. - * - * @departure rename - * "{@code conversion}" may be confusing as a method name - * since it does not indicate which CRS is the source or which is the target. - * The OGC 01-009 specification used the {@code toBase()} method name. - * By analogy with 01-009, GeoAPI defines a method name which contains the "{@code FromBase}" expression. */ - @UML(identifier="conversion", obligation=MANDATORY, specification=ISO_19111) + @UML(identifier="conversion", obligation=MANDATORY, specification=ISO_19111, version=2007) Conversion getConversionFromBase(); - - /** - * Returns the same datum as the base CRS datum. - * - * @return the datum of this derived CRS, which is the {@linkplain #getBaseCRS() base CRS} datum. - */ - @Override - default Datum getDatum() { - return getBaseCRS().getDatum(); - } } diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/GeocentricCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/GeocentricCRS.java index 9faaf9ab5..039fc3e35 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/GeocentricCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/GeocentricCRS.java @@ -43,7 +43,8 @@ * handling both using the {@code SC_GeodeticCRS} parent type. * GeoAPI keeps them since the distinction between those two types is in wide use. * - * @author Martin Desruisseaux (IRD) + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.0 * @since 1.0 * diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/GeodeticCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/GeodeticCRS.java index 02082198c..8b06966dd 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/GeodeticCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/GeodeticCRS.java @@ -25,17 +25,16 @@ /** - * A 2- or 3-dimensional coordinate reference system associated with a geodetic datum. - * Geodetic CRSs provide an accurate representation of the geometry of geographic features - * for a large portion of the Earth's surface. - * - *

This type of CRS can be used with coordinate systems of type + * A 2- or 3-dimensional CRS used over the whole planet or substantial parts of it. + * This type of CRS can be used with coordinate systems of type * {@link org.opengis.referencing.cs.CartesianCS}, * {@link org.opengis.referencing.cs.SphericalCS} or - * {@link org.opengis.referencing.cs.EllipsoidalCS}.

+ * {@link org.opengis.referencing.cs.EllipsoidalCS}. + * In the latter case, the {@link GeographicCRS} specialization should be used. * - * @author Martin Desruisseaux (IRD) - * @version 3.0 + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) + * @version 3.1 * @since 2.1 */ @UML(identifier="SC_GeodeticCRS", specification=ISO_19111, version=2007) diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/GeographicCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/GeographicCRS.java index da2febaf8..a48de9b27 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/GeographicCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/GeographicCRS.java @@ -53,7 +53,8 @@ * same goal. * * - * @author Martin Desruisseaux (IRD) + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.0 * @since 1.0 * diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/ImageCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/ImageCRS.java index 0db329de5..c78a4f8e4 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/ImageCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/ImageCRS.java @@ -28,7 +28,7 @@ /** - * A 2-dimensional engineering coordinate reference system applied to locations in images. + * A 2-dimensional engineering CRS applied to locations in images. * *
Note: * image coordinate reference systems are treated as a separate sub-type because a separate @@ -39,7 +39,7 @@ * {@link org.opengis.referencing.cs.CartesianCS} or * {@link org.opengis.referencing.cs.AffineCS}.

* - * @author Martin Desruisseaux (IRD) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.0 * @since 1.0 * diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/ParametricCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/ParametricCRS.java index 17abcd739..dc3993cde 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/ParametricCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/ParametricCRS.java @@ -27,7 +27,7 @@ /** - * A 1-dimensional coordinate reference system which uses parameter values or functions. + * A 1-dimensional CRS which uses parameter values or functions. * A coordinate reference system shall be of the parametric type if a physical or material * property or function is used as the dimension. * The values or functions can vary monotonically with height. @@ -40,6 +40,7 @@ *

This type of CRS can be used with coordinate systems of type * {@link org.opengis.referencing.cs.ParametricCS}.

* + * @author OGC Topic 2 (for abstract model and documentation) * @author Johann Sorel (Geomatys) * @version 3.1 * @since 3.1 diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/ProjectedCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/ProjectedCRS.java index 317cab426..34fbd4d73 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/ProjectedCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/ProjectedCRS.java @@ -37,7 +37,8 @@ *

This type of CRS can be used with coordinate systems of type * {@link org.opengis.referencing.cs.CartesianCS}.

* - * @author Martin Desruisseaux (IRD) + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.1 * @since 1.0 * @@ -45,7 +46,7 @@ * @see CRSFactory#createProjectedCRS(Map, GeographicCRS, Conversion, CartesianCS) */ @UML(identifier="SC_ProjectedCRS", specification=ISO_19111, version=2007) -public interface ProjectedCRS extends GeneralDerivedCRS { +public interface ProjectedCRS extends DerivedCRS { /** * Returns the base coordinate reference system, which must be geographic. * @@ -64,6 +65,8 @@ public interface ProjectedCRS extends GeneralDerivedCRS { /** * Returns the coordinate system, which shall be Cartesian. + * In the 3D case the ellipsoidal height from the base CRS + * is retained to form a three-dimensional Cartesian coordinate system. * * @return the Cartesian coordinate system. */ diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/SingleCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/SingleCRS.java index a26083d99..36dcd9849 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/SingleCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/SingleCRS.java @@ -28,45 +28,50 @@ /** - * Base type of CRS related to an object by a datum. + * Base type of CRS related to an object by a datum or datum ensemble. * For {@linkplain org.opengis.referencing.datum.GeodeticDatum geodetic} - * and {@linkplain org.opengis.referencing.datum.VerticalDatum vertical} datums, the object will be the Earth. + * and {@linkplain org.opengis.referencing.datum.VerticalDatum vertical} reference frame, + * the object will be the Earth or another celestial body. * - *

The valid coordinate system type and the datum type are constrained by the CRS type. - * For example, {@code GeographicCRS} can be associated only to {@code EllipsoidalCS} and - * {@code GeodeticDatum}.

+ *

The valid coordinate system type and the datum type are constrained by the CRS type. + * For example, {@code GeographicCRS} can be associated only to {@code EllipsoidalCS} and {@code GeodeticDatum}. + * The constraints are documented in the Javadoc of sub-interfaces.

* - * @author Martin Desruisseaux (IRD) - * @version 3.0 + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) + * @version 3.1 * @since 2.0 * - * @see org.opengis.referencing.cs.CoordinateSystem - * @see org.opengis.referencing.datum.Datum + * @see CoordinateSystem + * @see Datum */ @Classifier(Stereotype.ABSTRACT) -@UML(identifier="SC_SingleCRS", specification=ISO_19111, version=2007) +@UML(identifier="SingleCRS", specification=ISO_19111) public interface SingleCRS extends CoordinateReferenceSystem { /** - * Returns the coordinate system associated to this CRS. - * The coordinate system is composed of a set of coordinate axes with specified units of measure. - * This concept implies the mathematical rules that define how coordinate values are calculated + * Returns the coordinate system associated to this CRS. + * The coordinate system (CS) is composed of a set of coordinate axes with specified units of measure. + * The CS subtype implies the mathematical rules that define how coordinate values are calculated * from distances, angles and other geometric elements and vice versa. + * + * @return the coordinate system associated to this CRS. */ @Override @UML(identifier="coordinateSystem", obligation=MANDATORY, specification=ISO_19111) CoordinateSystem getCoordinateSystem(); /** - * Returns the datum associated directly or indirectly to this CRS. - * In the case of {@link GeneralDerivedCRS}, this method returns the - * datum of the {@linkplain GeneralDerivedCRS#getBaseCRS() base CRS}. + * Returns the datum associated directly or indirectly to this CRS. + * In the case of {@link DerivedCRS}, this method returns the + * datum of the {@linkplain DerivedCRS#getBaseCRS() base CRS}. * *

A datum specifies the relationship of a coordinate system to the object, thus ensuring that the abstract * mathematical concept “coordinate system” can be applied to the practical problem of describing positions of - * features on or near the earth's surface by means of coordinates. The object will generally, but not necessarily, - * be the earth. For certain coordinate reference systems, the object may be a moving platform.

+ * features on or near the planet's surface by means of coordinates. + * The object will generally, but not necessarily, be the Earth. + * For certain coordinate reference systems, the object may be a moving platform.

* - * @return the datum. + * @return the datum associated directly or indirectly to this CRS. * * @departure easeOfUse * The ISO specification declares the datum as absent when the association is indirect. diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/TemporalCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/TemporalCRS.java index 93c264d0e..2243a9412 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/TemporalCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/TemporalCRS.java @@ -34,7 +34,8 @@ *

This type of CRS can be used with coordinate systems of type * {@link org.opengis.referencing.cs.TimeCS}.

* - * @author Martin Desruisseaux (IRD) + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.0 * @since 1.0 * diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/VerticalCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/VerticalCRS.java index 3cf2df102..6fe6eff17 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/VerticalCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/VerticalCRS.java @@ -31,20 +31,15 @@ * Vertical CRSs make use of the direction of gravity to define the concept of height or depth, * but the relationship with gravity may not be straightforward. * - *

By implication, ellipsoidal heights (h) cannot be captured in a vertical coordinate - * reference system. Ellipsoidal heights cannot exist independently, but only as inseparable part - * of a 3D coordinate tuple defined in a geographic 3D coordinate reference system.

- * - *
Note: - * some applications may relax the above rule and accept ellipsoidal heights in some contexts. - * For example, as a transient state while parsing the legacy Well-Known Text version 1, - * or any other format based on legacy specifications where ellipsoidal heights were allowed as an - * independent axis. However, implementers are encouraged to assemble the full 3D CRS as soon as they can.
+ *

By implication, ellipsoidal heights (h) cannot be captured in a vertical CRS. + * Ellipsoidal heights cannot exist independently, but only as inseparable part of a 3D coordinate tuple + * defined in a geographic or projected 3D CRS.

* *

This type of CRS can be used with coordinate systems of type * {@link org.opengis.referencing.cs.VerticalCS}.

* - * @author Martin Desruisseaux (IRD) + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.0 * @since 1.0 * diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/package-info.java b/geoapi/src/main/java/org/opengis/referencing/crs/package-info.java index e1a586922..9b4be00f8 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/package-info.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/package-info.java @@ -18,43 +18,38 @@ /** * Reference systems by coordinates. - * A {@linkplain org.opengis.referencing.crs.CoordinateReferenceSystem Coordinate Reference System} (CRS) - * consists of one {@linkplain org.opengis.referencing.cs Coordinate System} + * A {@linkplain org.opengis.referencing.crs.CoordinateReferenceSystem Coordinate Reference System} + * (CRS) generally consists of one {@linkplain org.opengis.referencing.cs Coordinate System} * (a set of {@linkplain org.opengis.referencing.cs.CoordinateSystemAxis axes} with implied mathematical rules * for calculating distances and angles from coordinates) that is related to the Earth, another celestial body - * or a platform through one {@linkplain org.opengis.referencing.datum datum}. + * or a platform through one {@linkplain org.opengis.referencing.datum datum} or datum ensemble. * *

{@code CoordinateReferenceSystem} instances and their components shall be immutable. * For CRS defined on moving platforms such as cars, ships, aircraft and spacecraft, * transformation to an earth-fixed coordinate reference system may include a time element. - * Time-variability of coordinate reference systems may be covered by creating different - * {@code CoordinateReferenceSystem} instances, each with a different datum, for consecutive epochs. - * The date of realization of the datum shall then be included in its definition. - * Furthermore, it is recommended that the date of realization be included in the names of those datums - * and coordinate reference systems.

- * - *

Sub-types of coordinate reference system

- * Geodetic survey practice usually divides coordinate reference systems into a number of sub-types. - * The common classification criterion for sub-typing of coordinate reference systems can be described - * as the way in which they deal with earth curvature. This has a direct effect on the portion of the - * earth's surface that can be covered by that type of CRS with an acceptable degree of error. - * - *

Compound CRS

- * The traditional separation of horizontal and vertical position has resulted in coordinate reference systems - * that are horizontal (2D) in nature and vertical (1D). It is established practice to combine the horizontal - * coordinates of a point with a height or depth from a different CRS. The coordinate reference system - * to which these 3D coordinates are referenced combines the separate horizontal and vertical coordinate reference - * systems of the horizontal and vertical coordinates. Such a CRS is called a compound - * CRS. It consists of an ordered sequence of the two or more single coordinate reference systems. - * - *

Derived CRS

+ * For a dynamic CRS, locations on or near the surface of the Earth will move + * within the CRS due to crustal motion or deformation, therefor data needs a + * {@linkplain org.opengis.coordinate.CoordinateMetadata#getCoordinateEpoch() coordinate epoch} + * in addition of the CRS. In both cases, time-variability is handled by + * coordinate operations rather than changes in the CRS definition.

+ * + *

Compound CRS

+ * The traditional separation of horizontal, vertical and temporal position has resulted in different interfaces + * for the horizontal (2D), vertical (1D) and temporal (1D) components. It is established practice to combine the + * horizontal coordinates of a point with a height or depth from a different CRS, and sometime a time. + * The CRS to which these 3D or 4D coordinates are referenced is called a compound + * coordinate reference system. + * + *

Derived CRS

* Some coordinate reference systems are defined by applying a coordinate conversion to another CRS. - * Such a CRS is called a derived CRS and the coordinate reference system it - * was derived from by applying the conversion is called the source or base CRS. + * Such a CRS is called a derived coordinate reference system and the CRS + * it was derived from by applying the conversion is called the base CRS. * A coordinate conversion is an arithmetic operation with zero or more parameters that have defined values. - * The base CRS and derived CRS have the same datum. + * The base CRS and derived CRS have the same datum or datum ensemble. + * Projected CRSs are special cases of derived CRSs. * - * @author Martin Desruisseaux (IRD) + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.1 * @since 1.0 */ diff --git a/geoapi/src/main/java/org/opengis/referencing/datum/Datum.java b/geoapi/src/main/java/org/opengis/referencing/datum/Datum.java index 3bd5bf7a2..fc0e90955 100644 --- a/geoapi/src/main/java/org/opengis/referencing/datum/Datum.java +++ b/geoapi/src/main/java/org/opengis/referencing/datum/Datum.java @@ -31,9 +31,9 @@ /** - * Specifies the relationship of a {@linkplain org.opengis.referencing.cs.CoordinateSystem coordinate system} - * to the earth, thus creating a {@linkplain org.opengis.referencing.crs.CoordinateReferenceSystem coordinate - * reference system}. For {@linkplain org.opengis.referencing.crs.GeocentricCRS geodetic} and + * Specifies the relationship of a coordinate system to the earth, + * thus creating a coordinate reference system. + * For {@linkplain org.opengis.referencing.crs.GeocentricCRS geodetic} and * {@linkplain org.opengis.referencing.crs.VerticalCRS vertical} coordinate reference systems, * the datum relates the coordinate system to the Earth. With other types of coordinate reference systems, * the datum may relate the coordinate system to another physical or virtual object. @@ -43,7 +43,8 @@ * {@linkplain org.opengis.referencing.cs.CoordinateSystem coordinate systems}, documented in their * javadoc.

* - * @author Martin Desruisseaux (IRD) + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.1 * @since 1.0 * diff --git a/geoapi/src/main/java/org/opengis/referencing/datum/DatumAuthorityFactory.java b/geoapi/src/main/java/org/opengis/referencing/datum/DatumAuthorityFactory.java index eaed59919..c0e1888fe 100644 --- a/geoapi/src/main/java/org/opengis/referencing/datum/DatumAuthorityFactory.java +++ b/geoapi/src/main/java/org/opengis/referencing/datum/DatumAuthorityFactory.java @@ -28,7 +28,7 @@ /** - * Creates {@linkplain Datum datum} objects using authority codes. + * Creates datum objects using authority codes. * External authorities are used to manage definitions of objects used in this interface. * The definitions of these objects are referenced using code strings. * A commonly used authority is EPSG. @@ -43,7 +43,7 @@ * saying that the type or service is not supported. * * - * @author Martin Desruisseaux (IRD) + * @author Martin Desruisseaux (IRD, Geomatys) * @author Johann Sorel (Geomatys) * @version 3.1 * @since 1.0 diff --git a/geoapi/src/main/java/org/opengis/referencing/datum/DatumFactory.java b/geoapi/src/main/java/org/opengis/referencing/datum/DatumFactory.java index b99045dc8..aee7a6fb5 100644 --- a/geoapi/src/main/java/org/opengis/referencing/datum/DatumFactory.java +++ b/geoapi/src/main/java/org/opengis/referencing/datum/DatumFactory.java @@ -31,7 +31,7 @@ /** - * Builds up complex {@linkplain Datum datums} from simpler objects or values. + * Builds up complex datum objects from simpler objects or values. * {@code DatumFactory} allows applications to make {@linkplain Datum datums} * that cannot be created by a {@link DatumAuthorityFactory}. * This factory is very flexible, whereas the authority factory is easier to use. @@ -44,7 +44,7 @@ * the default is to throw an {@link UnimplementedServiceException} * with a message saying that the type or service is not supported. * - * @author Martin Desruisseaux (IRD) + * @author Martin Desruisseaux (IRD, Geomatys) * @author Johann Sorel (Geomatys) * @version 3.1 * @since 1.0 diff --git a/geoapi/src/main/java/org/opengis/referencing/datum/Ellipsoid.java b/geoapi/src/main/java/org/opengis/referencing/datum/Ellipsoid.java index c86b3ed21..9fb020790 100644 --- a/geoapi/src/main/java/org/opengis/referencing/datum/Ellipsoid.java +++ b/geoapi/src/main/java/org/opengis/referencing/datum/Ellipsoid.java @@ -67,7 +67,8 @@ * For precision, GeoAPI imports the {@code isIvfDefinitive} attribute from OGC 01-009 * to enable the user to establish which of the two parameters was used to define the instance. * - * @author Martin Desruisseaux (IRD) + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.1 * @since 1.0 * diff --git a/geoapi/src/main/java/org/opengis/referencing/datum/EngineeringDatum.java b/geoapi/src/main/java/org/opengis/referencing/datum/EngineeringDatum.java index 6db0434e9..2c3f91bb6 100644 --- a/geoapi/src/main/java/org/opengis/referencing/datum/EngineeringDatum.java +++ b/geoapi/src/main/java/org/opengis/referencing/datum/EngineeringDatum.java @@ -23,12 +23,24 @@ /** - * Defines the origin of an engineering coordinate reference system. An engineering datum is used - * in a region around that origin. This origin can be fixed with respect to the earth (such as a - * defined point at a construction site), or be a defined point on a moving vehicle (such as on a - * ship or satellite). + * Identification of the origin of an engineering (or local) coordinate reference system. + * An engineering datum is used in a region around that origin. + * This origin can be fixed with respect to the Earth (such as a defined point at a construction site), + * a defined point on a moving object (such as on a road vehicle, vessel, aircraft or spacecraft), + * or a point used to describe spatial location internally on an image. * - * @author Martin Desruisseaux (IRD) + *

When used for a region on Earth, engineering CRSs use a flat-Earth approximation: + * corrections for Earth-curvature are not applied. + * Typical applications are for civil engineering construction and building information management. + * Note that these applications are not restricted to using engineering CRSs: + * they often utilize projected and sometimes geodetic CRSs.

+ * + *

When used for an image internal coordinates, the CRS is not georeferenced. + * The image can be georeferenced by relating the engineering CRS to a geodetic + * or projected CRS through a coordinate transformation.

+ * + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.0 * @since 1.0 * diff --git a/geoapi/src/main/java/org/opengis/referencing/datum/GeodeticDatum.java b/geoapi/src/main/java/org/opengis/referencing/datum/GeodeticDatum.java index 1d242edd3..3edd87033 100644 --- a/geoapi/src/main/java/org/opengis/referencing/datum/GeodeticDatum.java +++ b/geoapi/src/main/java/org/opengis/referencing/datum/GeodeticDatum.java @@ -25,11 +25,20 @@ /** - * Defines the location and precise orientation in 3-dimensional space of a defined ellipsoid - * (or sphere) that approximates the shape of the earth. Used also for Cartesian coordinate - * system centered in this ellipsoid (or sphere). + * Location and orientation in 3-dimensional space of an ellipsoid (or sphere) that approximates the shape of the earth. + * A geodetic reference frame is used with three-dimensional or horizontal (two-dimensional) coordinate reference systems, + * and requires an ellipsoid definition and a prime meridian definition. + * This frame can also be used for a Cartesian coordinate system centered in the ellipsoid (or sphere). + * It is used to describe large portions of the planet's surface up to the entire planet's surface. * - * @author Martin Desruisseaux (IRD) + *

One ellipsoid can be specified with every geodetic datum, even if the ellipsoid is not used computationally. + * The latter may be the case when a Geocentric CRS is used, + * e.g., in the calculation of satellite orbit and ground positions from satellite observations. + * Although use of a Geocentric CRS apparently obviates the need of an ellipsoid, + * the ellipsoid usually played a role in the determination of the associated geodetic datum.

+ * + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.0 * @since 1.0 * @@ -42,17 +51,27 @@ @UML(identifier="CD_GeodeticDatum", specification=ISO_19111, version=2007) public interface GeodeticDatum extends Datum { /** - * Returns the ellipsoid. + * Returns an approximation of the surface of the geoid. + * Because of the area for which the approximation is valid + * — traditionally regionally, but with the advent of satellite positioning often globally — + * the ellipsoid is typically associated with Geographic and Projected CRSs. + * + *

An ellipsoid is defined either by its semi-major axis and inverse flattening, + * or by its semi-major axis and semi-minor axis. + * For some applications, for example small-scale mapping in atlases, + * a spherical approximation of the geoid's surface is used, + * requiring only the radius of the sphere to be specified.

* - * @return the ellipsoid. + * @return the approximation of the surface of the geoid. */ @UML(identifier="ellipsoid", obligation=MANDATORY, specification=ISO_19111) Ellipsoid getEllipsoid(); /** - * Returns the prime meridian. + * Returns the origin from which longitude values are specified. + * Most geodetic reference frames use Greenwich as their prime meridian. * - * @return the prime meridian. + * @return the origin from which longitude values are specified. */ @UML(identifier="primeMeridian", obligation=MANDATORY, specification=ISO_19111) PrimeMeridian getPrimeMeridian(); diff --git a/geoapi/src/main/java/org/opengis/referencing/datum/ImageDatum.java b/geoapi/src/main/java/org/opengis/referencing/datum/ImageDatum.java index 681448700..9203a6f86 100644 --- a/geoapi/src/main/java/org/opengis/referencing/datum/ImageDatum.java +++ b/geoapi/src/main/java/org/opengis/referencing/datum/ImageDatum.java @@ -25,17 +25,31 @@ /** - * Defines the origin of an image coordinate reference system. An image datum is used in a local - * context only. For an image datum, the anchor point is usually either the centre of the image - * or the corner of the image. + * Defines the origin of an image coordinate reference system. An image datum is used in a local context only. + * For an image datum, the anchor point is usually either the centre of the image or the corner of the image. + * The image datum definition applies regardless of whether or not the image is georeferenced. + * Georeferencing is performed through a transformation of image CRS to geodetic or projected CRS. + * The transformation plays no part in the image datum definition. * - *
Note: - * the image datum definition applies regardless of whether or not the image is georeferenced. - * Georeferencing is performed through a transformation of image CRS to geodetic - * or projected CRS. - * The transformation plays no part in the image datum definition.
+ *

The image pixel grid is defined as the set of lines of constant integer coordinate values. + * The term "image grid" is often used in other standards to describe the concept of Image CRS. + * However, care must be taken to correctly interpret this term in the context in which it is used. + * The term "grid cell" is often used as a substitute for the term "pixel".

* - * @author Martin Desruisseaux (IRD) + *

The grid lines of the image may be associated in two ways with the data attributes of the pixel or grid cell. + * The data attributes of the image usually represent an average or integrated value that is associated with the entire pixel. + * An image grid can be associated with this data in such a way that the grid lines run through the centres of the pixels. + * The cell centres will thus have integer coordinate values. + * In that case the attribute "pixel in cell" will have the value "cell centre". + * Alternatively, the image grid may be defined such that the grid lines + * associate with the cell or pixel corners rather than the cell centres. + * The cell centres will thus have noninteger coordinate values, the fractional parts always being 0.5. + * The attribute "pixel in cell" will now have the value "cell corner". + * This difference in perspective has no effect on the image interpretation, + * but is important for coordinate transformations involving this defined image.

+ * + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.0 * @since 1.0 * diff --git a/geoapi/src/main/java/org/opengis/referencing/datum/ParametricDatum.java b/geoapi/src/main/java/org/opengis/referencing/datum/ParametricDatum.java index 60a32c950..48e602d52 100644 --- a/geoapi/src/main/java/org/opengis/referencing/datum/ParametricDatum.java +++ b/geoapi/src/main/java/org/opengis/referencing/datum/ParametricDatum.java @@ -27,6 +27,7 @@ * A textual description and/or a set of parameters identifying a particular reference surface used as * the origin of a parametric coordinate system, including its position with respect to the Earth. * + * @author OGC Topic 2 (for abstract model and documentation) * @author Johann Sorel (Geomatys) * @version 3.1 * @since 3.1 diff --git a/geoapi/src/main/java/org/opengis/referencing/datum/PixelInCell.java b/geoapi/src/main/java/org/opengis/referencing/datum/PixelInCell.java index fde22dfef..89b016b70 100644 --- a/geoapi/src/main/java/org/opengis/referencing/datum/PixelInCell.java +++ b/geoapi/src/main/java/org/opengis/referencing/datum/PixelInCell.java @@ -27,12 +27,11 @@ /** * Specification of the way the image grid is associated with the image data attributes. + * This code list is similar to {@link org.opengis.metadata.spatial.PixelOrientation} + * except that the latter is more clearly restricted to the two-dimensional case. * - *
Note: - * this code list is similar to {@link org.opengis.metadata.spatial.PixelOrientation} - * except that the latter is more clearly restricted to the two-dimensional case.
- * - * @author Martin Desruisseaux (IRD) + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.1 * @since 1.0 * diff --git a/geoapi/src/main/java/org/opengis/referencing/datum/PrimeMeridian.java b/geoapi/src/main/java/org/opengis/referencing/datum/PrimeMeridian.java index 8d6aaf435..1757dbd0e 100644 --- a/geoapi/src/main/java/org/opengis/referencing/datum/PrimeMeridian.java +++ b/geoapi/src/main/java/org/opengis/referencing/datum/PrimeMeridian.java @@ -39,7 +39,8 @@ * shall be “Greenwich”. * * - * @author Martin Desruisseaux (IRD) + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.0.1 * @since 1.0 * diff --git a/geoapi/src/main/java/org/opengis/referencing/datum/TemporalDatum.java b/geoapi/src/main/java/org/opengis/referencing/datum/TemporalDatum.java index 772888772..f3d349b6d 100644 --- a/geoapi/src/main/java/org/opengis/referencing/datum/TemporalDatum.java +++ b/geoapi/src/main/java/org/opengis/referencing/datum/TemporalDatum.java @@ -29,7 +29,8 @@ /** * A temporal datum defines the origin of a temporal coordinate reference system. * - * @author Martin Desruisseaux (IRD) + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.1 * @since 1.0 * diff --git a/geoapi/src/main/java/org/opengis/referencing/datum/VerticalDatum.java b/geoapi/src/main/java/org/opengis/referencing/datum/VerticalDatum.java index 1030eceae..59e2d31fd 100644 --- a/geoapi/src/main/java/org/opengis/referencing/datum/VerticalDatum.java +++ b/geoapi/src/main/java/org/opengis/referencing/datum/VerticalDatum.java @@ -25,15 +25,16 @@ /** - * A textual description and/or a set of parameters identifying a particular reference level - * surface used as a zero-height surface. The description includes its position with respect - * to the Earth for any of the height types recognized by this standard. + * Identification of a particular reference level surface used as a zero-height surface. + * The description includes its position with respect to the Earth for any of the height + * types recognized by the ISO 19111 standard. * - *

There are several types of Vertical Datums, and each may place constraints on the - * {@linkplain org.opengis.referencing.cs.CoordinateSystemAxis Coordinate Axis} with which + *

There are several types of vertical reference frames, and each may place constraints + * on the {@linkplain org.opengis.referencing.cs.CoordinateSystemAxis Coordinate Axis} with which * it is combined to create a {@linkplain org.opengis.referencing.crs.VerticalCRS Vertical CRS}.

* - * @author Martin Desruisseaux (IRD) + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.0 * @since 1.0 * diff --git a/geoapi/src/main/java/org/opengis/referencing/datum/VerticalDatumType.java b/geoapi/src/main/java/org/opengis/referencing/datum/VerticalDatumType.java index f61b09e3a..301d947aa 100644 --- a/geoapi/src/main/java/org/opengis/referencing/datum/VerticalDatumType.java +++ b/geoapi/src/main/java/org/opengis/referencing/datum/VerticalDatumType.java @@ -43,7 +43,8 @@ * * @see VerticalDatum#getVerticalDatumType() * - * @author Martin Desruisseaux (IRD) + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.1 * @since 1.0 */ @@ -56,44 +57,70 @@ public final class VerticalDatumType extends CodeList { private static final long serialVersionUID = -8161084528823937553L; /** - * In some cases, for example oil exploration and production, a geological feature, such as the top - * or bottom of a geologically identifiable and meaningful subsurface layer, is used as a - * vertical datum. Other variations to the above three vertical datum types may exist - * and are all included in this type. - */ - @UML(identifier="other surface", obligation=CONDITIONAL, specification=ISO_19111) - public static final VerticalDatumType OTHER_SURFACE = new VerticalDatumType("OTHER_SURFACE"); - - /** - * The zero value of the associated vertical coordinate system axis is defined to approximate - * a constant potential surface, usually the geoid. Such a reference surface is usually - * determined by a national or scientific authority, and is then a well-known, named datum. + * The zero value is defined to approximate a constant potential surface, usually the geoid. + * Such a reference surface is usually determined by a national or scientific authority, + * and is then a well-known, named reference frame. */ @UML(identifier="geoidal", obligation=CONDITIONAL, specification=ISO_19111) public static final VerticalDatumType GEOIDAL = new VerticalDatumType("GEOIDAL"); /** - * The zero point of the vertical axis is defined by a surface that has meaning for the - * purpose which the associated vertical measurements are used for. For hydrographic charts, - * this is often a predicted nominal sea surface (i.e., without waves or other wind and current - * effects) that occurs at low tide. Depths are measured in the direction perpendicular - * (approximately) to the actual equipotential surfaces of the earth's gravity field, - * using such procedures as echo-sounding. + * The zero point is defined by a surface that has meaning + * for the purpose which the associated vertical measurements are used for. + * For hydrographic charts, this is often a predicted nominal sea surface + * (i.e., without waves or other wind and current effects) that occurs at low tide. + * Examples are Lowest Astronomical Tide and Lowest Low Water Spring. + * A different example is a sloping and undulating River Datum defined as + * the nominal river water surface occurring at a quantified river discharge. + * + *

Depths are measured in the direction perpendicular (approximately) to the actual equipotential + * surfaces of the earth's gravity field, using such procedures as echo-sounding.

*/ @UML(identifier="depth", obligation=CONDITIONAL, specification=ISO_19111) public static final VerticalDatumType DEPTH = new VerticalDatumType("DEPTH"); /** - * Atmospheric pressure is the basis for the definition of the origin of the - * associated vertical coordinate system axis. These are approximations of - * orthometric heights obtained with the help of a barometer or a barometric - * altimeter. These values are usually expressed in one of the following units: - * meters, feet, millibars (used to measure pressure levels), or theta value - * (units used to measure geopotential height). + * The origin of the vertical axis is based on atmospheric pressure. + * Atmospheric pressure may be used as the intermediary to determine height (barometric height determination) + * or it may be used directly as the vertical coordinate, against which other parameters are measured. + * Barometric values are usually expressed in one of the following units: + * meters, feet, millibars (used to measure pressure levels), + * or theta value (units used to measure geopotential height). + * + *

Barometric height determination is routinely used in aircraft. + * The altimeter (barometer) on board is set to the altitude of the airfield at the time of take-off, + * which corrects simultaneously for instantaneous air pressure and altitude of the airfield. + * The measured height value is commonly named "altitude".

+ * + *

In some land surveying applications, height differences between points are measured with barometers. + * To obtain absolute heights the measured height differences are added to the known heights of control points. + * In that case the vertical datum type is not barometric, but is the same as that of the vertical control network + * used to obtain the heights of the new points and its vertical datum type. + * The accuracy of this technique is limited, + * as it is affected strongly by the spatial and temporal variability of atmospheric pressure. + * This accuracy limitation impacts the precision of the associated vertical datum definition. + * The datum is usually the surface of constant atmospheric pressure approximately equating to mean sea level (MSL). + * The origin or anchor point is usually a point of known MSL height. + * The instruments are calibrated at this point by correcting for the instantaneous atmospheric pressure + * at sea level and the height of the point above MSL.

+ * + *

In meteorology, atmospheric pressure routinely takes the role as vertical coordinate in a CRS + * that is used as a spatial reference frame for meteorological parameters in the upper atmosphere. + * The origin of the datum is in that case the (hypothetical) zero atmospheric pressure and the positive + * vertical axis points down (to increasing pressure).

*/ @UML(identifier="barometric", obligation=CONDITIONAL, specification=ISO_19111) public static final VerticalDatumType BAROMETRIC = new VerticalDatumType("BAROMETRIC"); + /** + * The zero value is defined by a method not described by the other enumeration values in this class. + * In some cases, for example oil exploration and production, a geological feature, such as the top or + * bottom of a geologically identifiable and meaningful subsurface layer, is used as a vertical datum. + * Other variations to the above three vertical datum types may exist and are all included in this type. + */ + @UML(identifier="other surface", obligation=CONDITIONAL, specification=ISO_19111) + public static final VerticalDatumType OTHER_SURFACE = new VerticalDatumType("OTHER_SURFACE"); + /** * Constructs an element of the given name. * diff --git a/geoapi/src/main/java/org/opengis/referencing/datum/package-info.java b/geoapi/src/main/java/org/opengis/referencing/datum/package-info.java index 9a7470dde..8c93208d3 100644 --- a/geoapi/src/main/java/org/opengis/referencing/datum/package-info.java +++ b/geoapi/src/main/java/org/opengis/referencing/datum/package-info.java @@ -18,152 +18,17 @@ /** * Relationship of a Coordinate System (CS) to the Earth, another celestial body or a platform. - * A datum can be used as the basis for one-, two- or three-dimensional systems. * For {@linkplain org.opengis.referencing.crs.GeodeticCRS geodetic} - * and {@linkplain org.opengis.referencing.crs.VerticalCRS vertical} coordinate reference systems, - * the datum shall relate the coordinate system to the Earth. - * With other types of coordinate reference systems (CRS), the datum may relate the coordinate system - * to another physical or virtual object. In some applications of an - * {@linkplain org.opengis.referencing.crs.EngineeringCRS Engineering CRS}, - * the object may be a platform moving relative to the Earth. In these applications, - * the datum itself is not time-dependent, but any transformations of the associated coordinates - * to an Earth-fixed or other coordinate reference system shall contain time-dependent parameters. - * - *

Five subtypes of datum are specified: - * {@linkplain org.opengis.referencing.datum.GeodeticDatum geodetic}, - * {@linkplain org.opengis.referencing.datum.VerticalDatum vertical}, - * {@linkplain org.opengis.referencing.datum.EngineeringDatum engineering}, - * {@linkplain org.opengis.referencing.datum.ImageDatum image} and - * {@linkplain org.opengis.referencing.datum.TemporalDatum temporal}. - * Each datum subtype can be associated only with specific types of coordinate reference systems:

- * - *
    - *
  • A geodetic datum is used with three-dimensional or horizontal (two-dimensional) coordinate reference systems, - * and requires an ellipsoid definition and a prime meridian definition. - * It is used to describe large portions of the earth's surface up to the entire earth's surface.
  • - *
  • A vertical datum can only be associated with a vertical coordinate reference system.
  • - *
  • Image datum and engineering datum are both used in a local context only: - * to describe the origin of an image and the origin of an engineering (or local) coordinate reference system.
  • - *
- * - *

Vertical datum

- *

Further sub-typing is required to describe vertical datums adequately. - * The following types of vertical datum are distinguished:

- *
    - *
  • Geoidal
    - * The zero value of the associated (vertical) coordinate system axis is defined - * to approximate a constant potential surface, usually the geoid. Such a reference - * surface is usually determined by a national or scientific authority and is then - * a well known, named datum. This is the default vertical datum type, because it is - * the most common one encountered.

  • - * - *
  • Depth
    - * The zero point of the vertical axis is defined by a surface that has meaning for - * the purpose the associated vertical measurements are used for. For hydrographic - * charts, this is often a predicted nominal sea surface (i.e., without waves or - * other wind and current effects) that occurs at low tide. Examples are Lowest - * Astronomical Tide and Lowest Low Water Spring. A different example is a sloping - * and undulating River Datum defined as the nominal river water surface occurring - * at a quantified river discharge.

  • - * - *
  • Barometric
    - * A vertical datum is of type "barometric" if atmospheric pressure is the basis - * for the definition of the origin. Atmospheric pressure may be used as the - * intermediary to determine height (barometric height determination) or it may - * be used directly as the vertical coordinate, against which other parameters are - * measured. The latter case is applied routinely in meteorology.

    - * - *

    Barometric height determination is routinely used in aircraft. - * The altimeter (barometer) on board is set to the altitude of the airfield at the - * time of take-off, which corrects simultaneously for instantaneous air pressure and - * altitude of the airfield. The measured height value is commonly named "altitude".

    - * - *

    In some land surveying applications height differences between - * points are measured with barometers. To obtain absolute heights the measured height - * differences are added to the known heights of control points. In that case the vertical - * datum type is not barometric, but is the same as that of the vertical control network - * used to obtain the heights of the new points and its vertical datum type.

    - * - *

    The accuracy of this technique is limited, as it is affected - * strongly by the spatial and temporal variability of atmospheric pressure. This - * accuracy limitation impacts the precision of the associated vertical datum definition. - * The datum is usually the surface of constant atmospheric pressure approximately - * equating to mean sea level (MSL). The origin or anchor point is usually a point - * of known MSL height. The instruments are calibrated at this point by correcting - * for the instantaneous atmospheric pressure at sea level and the height of the - * point above MSL.

    - * - *

    In meteorology, atmospheric pressure routinely takes the role as vertical coordinate in a CRS - * that is used as a spatial reference frame for meteorological parameters in the upper atmosphere. - * The origin of the datum is in that case the (hypothetical) zero atmospheric pressure and the positive - * vertical axis points down (to increasing pressure).

  • - * - *
  • Other surface
    - * In some cases, e.g. oil exploration and production, geological features, - * i.e., the top or bottom of a geologically identifiable and meaningful subsurface - * layer, are sometimes used as a vertical datum. Other variations to the above three - * vertical datum types may exist and are all bracketed in this category.

  • - *
- * - *

Image datum

- *

The image pixel grid is defined as the set of lines of constant - * integer coordinate values. The term "image grid" is often used in other standards to - * describe the concept of Image CRS. However, care must be taken to correctly interpret - * this term in the context in which it is used. The term "grid cell" is often used as a - * substitute for the term "pixel".

- * - *

The grid lines of the image may be associated in two ways with - * the data attributes of the pixel or grid cell (ISO CD 19123). The data attributes - * of the image usually represent an average or integrated value that is associated - * with the entire pixel.

- * - *

An image grid can be associated with this data in such a way - * that the grid lines run through the centres of the pixels. The cell centres will - * thus have integer coordinate values. In that case the attribute "pixel in cell" - * will have the value "cell centre".

- * - *

Alternatively, the image grid may be defined such that the - * grid lines associate with the cell or pixel corners rather than the cell centres. - * The cell centres will thus have noninteger coordinate values, the fractional parts - * always being 0.5. ISO CD 19123 calls the grid points in this latter case "posts" - * and associated image data: "matrix data". The attribute "pixel in cell" will now - * have the value "cell corner".

- * - *

This difference in perspective has no effect on the image - * interpretation, but is important for coordinate transformations involving this - * defined image.

- * - *

Prime meridian

- *

A prime meridian defines the origin from which longitude values - * are specified. Most geodetic datums use Greenwich as their prime meridian. A prime - * meridian description is not needed for any datum type other than geodetic, or if the - * datum type is geodetic and the prime meridian is Greenwich. The prime meridian - * description is mandatory if the datum type is geodetic and its prime meridian - * is not Greenwich.

- * - *

Ellipsoid

- *

An ellipsoid is defined that approximates the surface of the - * geoid. Because of the area for which the approximation is valid - traditionally - * regionally, but with the advent of satellite positioning often globally - the - * ellipsoid is typically associated with Geographic and Projected CRSs. An ellipsoid - * specification shall not be provided if the datum type not geodetic.

- * - *

One ellipsoid must be specified with every geodetic datum, - * even if the ellipsoid is not used computationally. - * The latter may be the case when a Geocentric CRS is used, - * e.g., in the calculation of satellite orbit and ground positions from satellite observations. - * Although use of a Geocentric CRS apparently obviates the need of an ellipsoid, - * the ellipsoid usually played a role in the determination of the associated geodetic datum. - * Furthermore, one or more Geographic CRSs may be based on the same geodetic datum, - * which requires the correct ellipsoid the associated with any given geodetic datum.

- * - *

An ellipsoid is defined either by its semi-major axis and - * inverse flattening, or by its semi-major axis and semi-minor axis. For some - * applications, for example small-scale mapping in atlases, a spherical approximation - * of the geoid's surface is used, requiring only the radius of the sphere to be - * specified.

- * - * @author Martin Desruisseaux (IRD) + * and {@linkplain org.opengis.referencing.crs.VerticalCRS vertical} + * coordinate reference systems (CRS), the datum is known as reference frame + * and shall relate the coordinate system to the Earth or other celestial body. + * With other types of CRSs, the datum may relate the coordinate system + * to another physical or virtual object. It may be a moving platform such as a car. + * The datum itself is not time-dependent, but any transformations of the associated coordinates + * to an Earth-fixed or other coordinate reference system may contain time-dependent parameters. + * + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.1 * @since 1.0 */ diff --git a/geoapi/src/main/java/org/opengis/referencing/operation/Conversion.java b/geoapi/src/main/java/org/opengis/referencing/operation/Conversion.java index cdcb98edc..2ffe48559 100644 --- a/geoapi/src/main/java/org/opengis/referencing/operation/Conversion.java +++ b/geoapi/src/main/java/org/opengis/referencing/operation/Conversion.java @@ -50,7 +50,7 @@ public interface Conversion extends SingleOperation { /** * Returns the source CRS. * Conversions may have a source CRS that is not specified here, - * but through {@link org.opengis.referencing.crs.GeneralDerivedCRS#getBaseCRS()} instead. + * but through {@link org.opengis.referencing.crs.DerivedCRS#getBaseCRS()} instead. * * @return the source CRS, or {@code null} if not available. */ @@ -61,7 +61,7 @@ public interface Conversion extends SingleOperation { /** * Returns the target CRS. * Conversions may have a target CRS that is not specified here, - * but through {@link org.opengis.referencing.crs.GeneralDerivedCRS} instead. + * but through {@link org.opengis.referencing.crs.DerivedCRS} instead. * * @return the target CRS, or {@code null} if not available. */ diff --git a/geoapi/src/main/java/org/opengis/referencing/operation/CoordinateOperation.java b/geoapi/src/main/java/org/opengis/referencing/operation/CoordinateOperation.java index 47049b99b..9618c306f 100644 --- a/geoapi/src/main/java/org/opengis/referencing/operation/CoordinateOperation.java +++ b/geoapi/src/main/java/org/opengis/referencing/operation/CoordinateOperation.java @@ -102,7 +102,7 @@ public interface CoordinateOperation extends IdentifiedObject { /** * Returns the source CRS. The source CRS is mandatory for {@linkplain Transformation transformations} only. * {@linkplain Conversion Conversions} may have a source CRS that is not specified here, but through - * {@link org.opengis.referencing.crs.GeneralDerivedCRS#getBaseCRS()} instead. + * {@link org.opengis.referencing.crs.DerivedCRS#getBaseCRS()} instead. * * @return the source CRS, or {@code null} if not available. * @@ -115,7 +115,7 @@ public interface CoordinateOperation extends IdentifiedObject { /** * Returns the target CRS. The target CRS is mandatory for {@linkplain Transformation transformations} only. * {@linkplain Conversion Conversions} may have a target CRS that is not specified here, but through - * {@link org.opengis.referencing.crs.GeneralDerivedCRS} instead. + * {@link org.opengis.referencing.crs.DerivedCRS} instead. * * @return the target CRS, or {@code null} if not available. * diff --git a/geoapi/src/main/java/org/opengis/referencing/operation/CoordinateOperationAuthorityFactory.java b/geoapi/src/main/java/org/opengis/referencing/operation/CoordinateOperationAuthorityFactory.java index fd4a75e09..f8a43802d 100644 --- a/geoapi/src/main/java/org/opengis/referencing/operation/CoordinateOperationAuthorityFactory.java +++ b/geoapi/src/main/java/org/opengis/referencing/operation/CoordinateOperationAuthorityFactory.java @@ -73,8 +73,8 @@ public interface CoordinateOperationAuthorityFactory extends AuthorityFactory { CoordinateOperation createCoordinateOperation(String code) throws FactoryException; /** - * Creates operations from {@linkplain CoordinateReferenceSystem coordinate reference system} - * codes. This method returns only the operations declared by the authority, with preferred + * Creates operations from Coordinate Reference System codes. + * This method returns only the operations declared by the authority, with preferred * operations first. This method doesn't need to compute operations from {@code source} to * {@code target} CRS if no such operations were explicitly defined in the authority database. * Computation of arbitrary operations can be performed by diff --git a/geoapi/src/main/java/org/opengis/referencing/operation/package-info.java b/geoapi/src/main/java/org/opengis/referencing/operation/package-info.java index f65b28e78..81d295160 100644 --- a/geoapi/src/main/java/org/opengis/referencing/operation/package-info.java +++ b/geoapi/src/main/java/org/opengis/referencing/operation/package-info.java @@ -92,7 +92,7 @@ * and/or coordinate conversions.

* *

The source and target coordinate reference system of a coordinate conversion - * are defined in the {@link org.opengis.referencing.crs.GeneralDerivedCRS}, + * are defined in the {@link org.opengis.referencing.crs.DerivedCRS}, * by specifying the base (i.e., source) CRS and the defining conversion. * The derived coordinate reference system itself is the target CRS in this situation. * When used in a concatenated operation, the conversion's source and target coordinate reference diff --git a/geoapi/src/main/java/org/opengis/referencing/package-info.java b/geoapi/src/main/java/org/opengis/referencing/package-info.java index ae7a728d3..825d2bb07 100644 --- a/geoapi/src/main/java/org/opengis/referencing/package-info.java +++ b/geoapi/src/main/java/org/opengis/referencing/package-info.java @@ -48,6 +48,7 @@ * there do not need to be any constraints on operation sequencing. * This means that these interfaces can be used in parallel computing environments (e.g. Internet servers). * + * @author OGC Topic 2 (for abstract model and documentation) * @author Martin Desruisseaux (IRD, Geomatys) * @author Ely Conn (Leica Geosystems Geospatial Imaging, LLC) * @version 3.1 diff --git a/geoapi/src/main/python/opengis/referencing/crs.py b/geoapi/src/main/python/opengis/referencing/crs.py index 91f1be077..487ebd2f7 100644 --- a/geoapi/src/main/python/opengis/referencing/crs.py +++ b/geoapi/src/main/python/opengis/referencing/crs.py @@ -193,7 +193,7 @@ def datum(self) -> EngineeringDatum: pass -class GeneralDerivedCRS(SingleCRS): +class DerivedCRS(SingleCRS): """ A coordinate reference system that is defined by its coordinate conversion from another coordinate reference system (not by a datum). @@ -239,13 +239,6 @@ def datum(self) -> GeodeticDatum: pass -class DerivedCRS(GeneralDerivedCRS): - """ - A coordinate reference system that is defined by its coordinate conversion from another coordinate reference system - but is not a projected coordinate reference system. - """ - - class GeographicCRS(GeodeticCRS): """ A coordinate reference system based on an ellipsoidal approximation of the geoid; this provides an accurate @@ -264,7 +257,7 @@ def coordinate_system(self) -> EllipsoidalCS: pass -class ProjectedCRS(GeneralDerivedCRS): +class ProjectedCRS(DerivedCRS): """ A 2D coordinate reference system used to approximate the shape of the earth on a planar surface. """ diff --git a/geoapi/src/main/python/opengis/referencing/operation.py b/geoapi/src/main/python/opengis/referencing/operation.py index f8e096343..3cc6bcb10 100644 --- a/geoapi/src/main/python/opengis/referencing/operation.py +++ b/geoapi/src/main/python/opengis/referencing/operation.py @@ -235,7 +235,7 @@ def source_crs(self) -> CoordinateReferenceSystem: """ Returns the source CRS. The source CRS is mandatory for transformations only. Conversions may have a source CRS that is not specified here, but through - ``GeneralDerivedCRS.getBaseCRS()`` instead. + ``DerivedCRS.getBaseCRS()`` instead. :return: The source CRS, or null if not available. :rtype: CoordinateReferenceSystem @@ -247,7 +247,7 @@ def target_crs(self) -> CoordinateReferenceSystem: """ Returns the target CRS. The target CRS is mandatory for transformations only. Conversions may have a target CRS that is not specified here, but through - ``GeneralDerivedCRS`` instead. + ``DerivedCRS`` instead. :return: The target CRS, or null if not available. :rtype: CoordinateReferenceSystem @@ -417,7 +417,7 @@ class Conversion(SingleOperation): def source_crs(self) -> CoordinateReferenceSystem: """ Returns the source CRS. Conversions may have a source CRS that is not specified here, but through - ``GeneralDerivedCRS.getBaseCRS()`` instead. + ``DerivedCRS.getBaseCRS()`` instead. :return: The source CRS, or null if not available. :rtype: CoordinateReferenceSystem @@ -428,7 +428,7 @@ def source_crs(self) -> CoordinateReferenceSystem: def target_crs(self) -> CoordinateReferenceSystem: """ Returns the target CRS. Conversions may have a target CRS that is not specified here, but through - ``GeneralDerivedCRS`` instead. + ``DerivedCRS`` instead. :return: The target CRS, or null if not available. :rtype: CoordinateReferenceSystem diff --git a/geoapi/src/main/resources/org/opengis/annotation/class-index.properties b/geoapi/src/main/resources/org/opengis/annotation/class-index.properties index f78222ab1..2fd744c00 100644 --- a/geoapi/src/main/resources/org/opengis/annotation/class-index.properties +++ b/geoapi/src/main/resources/org/opengis/annotation/class-index.properties @@ -39,6 +39,7 @@ CI_RoleCode=org.opengis.metadata.citation.Role CI_Series=org.opengis.metadata.citation.Series CI_Telephone=org.opengis.metadata.citation.Telephone CI_TelephoneTypeCode=org.opengis.metadata.citation.TelephoneType +CRS=org.opengis.referencing.crs.CoordinateReferenceSystem CS_AffineCS=org.opengis.referencing.cs.AffineCS CS_AxisDirection=org.opengis.referencing.cs.AxisDirection CS_CartesianCS=org.opengis.referencing.cs.CartesianCS @@ -226,7 +227,6 @@ PT_FreeText=org.opengis.util.InternationalString QE_Usability=org.opengis.metadata.quality.Usability RS_Identifier=org.opengis.referencing.ReferenceIdentifier RS_ReferenceSystem=org.opengis.referencing.ReferenceSystem -SC_CRS=org.opengis.referencing.crs.CoordinateReferenceSystem SC_CompoundCRS=org.opengis.referencing.crs.CompoundCRS SC_DerivedCRS=org.opengis.referencing.crs.DerivedCRS SC_EngineeringCRS=org.opengis.referencing.crs.EngineeringCRS @@ -236,7 +236,6 @@ SC_GeodeticCRS=org.opengis.referencing.crs.GeodeticCRS SC_GeographicCRS=org.opengis.referencing.crs.GeographicCRS SC_ImageCRS=org.opengis.referencing.crs.ImageCRS SC_ProjectedCRS=org.opengis.referencing.crs.ProjectedCRS -SC_SingleCRS=org.opengis.referencing.crs.SingleCRS SC_TemporalCRS=org.opengis.referencing.crs.TemporalCRS SC_VerticalCRS=org.opengis.referencing.crs.VerticalCRS SV_CoupledResource=org.opengis.metadata.identification.CoupledResource @@ -245,3 +244,4 @@ SV_OperationChainMetadata=org.opengis.metadata.identification.OperationChainMeta SV_OperationMetadata=org.opengis.metadata.identification.OperationMetadata SV_ParameterDirection=org.opengis.parameter.ParameterDirection SV_ServiceIdentification=org.opengis.metadata.identification.ServiceIdentification +SingleCRS=org.opengis.referencing.crs.SingleCRS diff --git a/geoapi/src/shared/java/org/opengis/geoapi/NameSpaces.java b/geoapi/src/shared/java/org/opengis/geoapi/NameSpaces.java index 7ec97aedd..61e0a3692 100644 --- a/geoapi/src/shared/java/org/opengis/geoapi/NameSpaces.java +++ b/geoapi/src/shared/java/org/opengis/geoapi/NameSpaces.java @@ -148,7 +148,8 @@ public QName name(final Class type, final Map components; /** - * Creates a new mock. + * Creates a new mock with only single CRSs. * * @param components the components of this compound CRS. */ @@ -51,6 +51,13 @@ final class CompoundCRSMock implements CompoundCRS, Identifier { } } + /** + * Creates a new mock with a nested compound CRS. + */ + CompoundCRSMock(final CoordinateSystemMock head, final CompoundCRSMock tail) { + components = List.of(head, tail); + } + /** * {@return a dummy name for this compound CRS}. */ diff --git a/geoapi/src/test/java/org/opengis/referencing/crs/CompoundCRSTest.java b/geoapi/src/test/java/org/opengis/referencing/crs/CompoundCRSTest.java index 75ed14230..c0f767c83 100644 --- a/geoapi/src/test/java/org/opengis/referencing/crs/CompoundCRSTest.java +++ b/geoapi/src/test/java/org/opengis/referencing/crs/CompoundCRSTest.java @@ -17,6 +17,7 @@ */ package org.opengis.referencing.crs; +import java.util.List; import org.opengis.referencing.cs.CoordinateSystem; import org.junit.jupiter.api.Test; @@ -48,8 +49,8 @@ public void testCoordinateSystem() { new CoordinateSystemMock(2, 2, 3)); final CoordinateSystem cs = crs.getCoordinateSystem(); - verifyAxes(cs, "Coordinate system of " + CompoundCRSMock.NAME, - "x0:0", "x0:1", "x1:2", "x2:3", "x2:4"); + assertTrue(cs.getName().getCode().startsWith("Coordinate system of " + CompoundCRSMock.NAME)); + verifyAxes(cs, "x0:0", "x0:1", "x1:2", "x2:3", "x2:4"); String message = assertThrows(IndexOutOfBoundsException.class, () -> cs.getAxis(6)).getMessage(); assertTrue(message.contains("6")); @@ -58,15 +59,31 @@ public void testCoordinateSystem() { assertTrue(message.contains("-1")); } + /** + * Tests {@link CompoundCRS#getSingleComponents()}. + */ + @Test + public void testGetSingleComponents() { + final CompoundCRS crs = new CompoundCRSMock( + new CoordinateSystemMock(0, 2, 0), + new CompoundCRSMock( + new CoordinateSystemMock(1, 1, 2), + new CoordinateSystemMock(2, 2, 3))); + + List components = crs.getSingleComponents(); + assertEquals(3, components.size()); + verifyAxes(components.get(0).getCoordinateSystem(), "x0:0", "x0:1"); + verifyAxes(components.get(1).getCoordinateSystem(), "x1:2"); + verifyAxes(components.get(2).getCoordinateSystem(), "x2:3", "x2:4"); + } + /** * Verifies that the given coordinate system has the expected axes. * * @param cs the coordinate system to validate. - * @param name the expected coordinate system name. * @param axes the expected coordinate system axes (identified by abbreviations). */ - private static void verifyAxes(final CoordinateSystem cs, final String name, final String... axes) { - assertTrue(cs.getName().getCode().startsWith(name)); + private static void verifyAxes(final CoordinateSystem cs, final String... axes) { assertEquals(axes.length, cs.getDimension()); for (int i=0; i Date: Wed, 20 Mar 2024 17:21:33 +0100 Subject: [PATCH 04/20] Partial upgrade to ISO 19111:2019 for interfaces in the `org.opengis.referencing.crs` package. Start the upgrade of interfaces in the `org.opengis.referencing.cs` package. --- .../org/opengis/test/ToleranceModifier.java | 4 +- .../test/referencing/CRSValidator.java | 2 +- .../opengis/annotation/ResourceBundles.java | 2 +- .../metadata/extent/VerticalExtent.java | 2 +- .../opengis/referencing/AuthorityFactory.java | 4 +- .../referencing/crs/CRSAuthorityFactory.java | 2 +- .../opengis/referencing/crs/CRSFactory.java | 2 +- .../opengis/referencing/crs/CompoundCRS.java | 13 ++-- .../opengis/referencing/crs/CompoundCS.java | 12 +++- .../opengis/referencing/crs/DerivedCRS.java | 65 ++++++++++++------- .../referencing/crs/EngineeringCRS.java | 38 +++++++++-- .../referencing/crs/GeocentricCRS.java | 22 +++---- .../opengis/referencing/crs/GeodeticCRS.java | 38 +++++++++-- .../referencing/crs/GeographicCRS.java | 25 +++---- .../referencing/crs/ParametricCRS.java | 43 +++++++++--- .../opengis/referencing/crs/ProjectedCRS.java | 43 +++++++++--- .../opengis/referencing/crs/SingleCRS.java | 44 +++++++++++-- .../opengis/referencing/crs/TemporalCRS.java | 37 +++++++++-- .../opengis/referencing/crs/VerticalCRS.java | 39 +++++++++-- .../referencing/cs/CSAuthorityFactory.java | 2 +- .../opengis/referencing/cs/package-info.java | 21 +++--- .../org/opengis/referencing/datum/Datum.java | 3 +- .../datum/DatumAuthorityFactory.java | 2 +- .../referencing/datum/DatumEnsemble.java | 38 +++++++++++ .../CoordinateOperationAuthorityFactory.java | 5 +- .../opengis/annotation/class-index.properties | 16 +++-- .../java/org/opengis/geoapi/Content.java | 1 + .../java/org/opengis/geoapi/NameSpaces.java | 1 + .../opengis/geoapi/MethodSignatureTest.java | 2 +- .../referencing/crs/CompoundCRSTest.java | 4 +- 30 files changed, 393 insertions(+), 139 deletions(-) create mode 100644 geoapi/src/main/java/org/opengis/referencing/datum/DatumEnsemble.java diff --git a/geoapi-conformance/src/main/java/org/opengis/test/ToleranceModifier.java b/geoapi-conformance/src/main/java/org/opengis/test/ToleranceModifier.java index 045e8d95f..866a38d58 100644 --- a/geoapi-conformance/src/main/java/org/opengis/test/ToleranceModifier.java +++ b/geoapi-conformance/src/main/java/org/opengis/test/ToleranceModifier.java @@ -64,7 +64,7 @@ public interface ToleranceModifier { * geographic coordinates. This modifier is identical to the {@link #GEOGRAPHIC} tolerance * modifier, except that φ and λ axes are interchanged. This is the most common * modifier used when testing {@link GeographicCRS} instances created from the - * EPSG database. + * EPSG geodetic registry. * * @see ToleranceModifiers#geographic(int, int) */ @@ -88,7 +88,7 @@ public interface ToleranceModifier { * the result of an reverse projection. This modifier is identical to the * {@link #PROJECTION} tolerance modifier, except that φ and λ axes are * interchanged. This is the most common modifier used when testing {@link ProjectedCRS} - * instances created from the EPSG database. + * instances created from the EPSG geodetic registry. * * @see ToleranceModifiers#projection(int, int) */ diff --git a/geoapi-conformance/src/main/java/org/opengis/test/referencing/CRSValidator.java b/geoapi-conformance/src/main/java/org/opengis/test/referencing/CRSValidator.java index b2d34fd62..12bdfd229 100644 --- a/geoapi-conformance/src/main/java/org/opengis/test/referencing/CRSValidator.java +++ b/geoapi-conformance/src/main/java/org/opengis/test/referencing/CRSValidator.java @@ -431,7 +431,7 @@ public void validate(final CompoundCRS object) { /* * Verify the components again, but without nested compound CRS. */ - final List singles = object.getSingleComponents(); + final List singles = object.getFlattenedComponents(); mandatory("CompoundCRS: shall have components.", singles); if (singles != null) { int dimension = 0; diff --git a/geoapi/src/main/java/org/opengis/annotation/ResourceBundles.java b/geoapi/src/main/java/org/opengis/annotation/ResourceBundles.java index 72abc1c2f..a056cf303 100644 --- a/geoapi/src/main/java/org/opengis/annotation/ResourceBundles.java +++ b/geoapi/src/main/java/org/opengis/annotation/ResourceBundles.java @@ -143,5 +143,5 @@ public static Properties classIndex() throws IOException { /** * Number of lines in the {@code "class-index.properties"} file. */ - static final int INDEX_CAPACITY = 247; + static final int INDEX_CAPACITY = 249; } diff --git a/geoapi/src/main/java/org/opengis/metadata/extent/VerticalExtent.java b/geoapi/src/main/java/org/opengis/metadata/extent/VerticalExtent.java index 7e5387d1f..2b35cddc3 100644 --- a/geoapi/src/main/java/org/opengis/metadata/extent/VerticalExtent.java +++ b/geoapi/src/main/java/org/opengis/metadata/extent/VerticalExtent.java @@ -31,7 +31,7 @@ * ISO 19115 provides two ways to define a coordinate reference system, * with the restriction that only one of those two ways can be used: *

    - *
  1. {@code verticalCRS} of type {@code SC_VerticalCRS} (from ISO 19111),
  2. + *
  3. {@code verticalCRS} of type {@code VerticalCRS} (from ISO 19111),
  4. *
  5. {@code verticalCRSId} of type {@code MD_ReferenceSystem} (from ISO 19115).
  6. *
* GeoAPI provides only the first way, because the {@code MD_ReferenceSystem} type diff --git a/geoapi/src/main/java/org/opengis/referencing/AuthorityFactory.java b/geoapi/src/main/java/org/opengis/referencing/AuthorityFactory.java index e10be77bb..6416560ac 100644 --- a/geoapi/src/main/java/org/opengis/referencing/AuthorityFactory.java +++ b/geoapi/src/main/java/org/opengis/referencing/AuthorityFactory.java @@ -35,8 +35,8 @@ * An authority is an organization that maintains definitions of authority codes. * An authority code is a compact string defined by an authority to reference a particular referencing object. * - *

For example, the European Petroleum Survey Group (EPSG) maintains a database - * of coordinate reference systems, and other spatial referencing objects, where each object has a code number ID. + *

For example, the EPSG geodetic registry is a database of coordinate + * reference systems, and other spatial referencing objects, where each object has a code number ID. * For example, the EPSG code for a WGS84 Lat/Lon CRS is 4326.

* * @author OGC Topic 2 (for abstract model and documentation) diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/CRSAuthorityFactory.java b/geoapi/src/main/java/org/opengis/referencing/crs/CRSAuthorityFactory.java index af7a8271b..d23eafc3f 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/CRSAuthorityFactory.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/CRSAuthorityFactory.java @@ -31,7 +31,7 @@ * Creates coordinate reference systems using authority codes. * External authorities are used to manage definitions of objects used in this interface. * The definitions of these objects are referenced using code strings. - * A commonly used authority is EPSG. + * A commonly used authority is the EPSG geodetic registry. * *

Default methods

* All {@code create(…)} methods in this interface are optional. diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/CRSFactory.java b/geoapi/src/main/java/org/opengis/referencing/crs/CRSFactory.java index 7b92b98fa..98af4f8b8 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/CRSFactory.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/CRSFactory.java @@ -34,7 +34,7 @@ /** * Builds up complex Coordinate Reference Systems from simpler objects or values. * {@code CRSFactory} allows applications to make - * {@linkplain CoordinateReferenceSystem Coordinate Reference Systems} + * {@linkplain CoordinateReferenceSystem Coordinate Reference Systems} (CRS) * that cannot be created by a {@link CRSAuthorityFactory}. * This factory is very flexible, whereas the authority factory is easier to use. * So {@link CRSAuthorityFactory} can be used to make "standard" coordinate reference systems, diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/CompoundCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/CompoundCRS.java index dfd0a8983..2709e7f64 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/CompoundCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/CompoundCRS.java @@ -31,9 +31,12 @@ /** * A CRS describing the position of points through two or more independent CRSs. - * For spatial coordinates, a number of constraints exist for the construction of Compound CRSs. + * Two CRSs are independent of each other if coordinate values in one cannot be converted or + * transformed into coordinate values in the other. + * + *

For spatial coordinates, a number of constraints exist for the construction of compound CRSs. * For example, the CRSs that are combined should not contain any duplicate or redundant axes. - * Valid combinations include (non-exhaustive list): + * Valid combinations include (non-exhaustive list):

* *
    *
  • Geographic 2D + Vertical
  • @@ -61,7 +64,7 @@ public interface CompoundCRS extends CoordinateReferenceSystem { /** * Returns the ordered list of CRS components. * The returned list may contain nested compound CRS. - * For a list without nesting, as required by ISO 19111, see {@link #getSingleComponents()}. + * For a list without nesting, as required by ISO 19111, see {@link #getFlattenedComponents()}. * *

    Why nested compound CRS

    * The use of nested compound CRSs can avoid metadata lost when a temporal CRS @@ -77,7 +80,7 @@ public interface CompoundCRS extends CoordinateReferenceSystem { * * @departure generalization * Added as an alternative to the association defined by ISO 19111 for resolving the problem of metadata lost. - * The ISO 19111 requirement is still available as the {@link #getSingleComponents()} method. + * The ISO 19111 requirement is still available as the {@link #getFlattenedComponents()} method. */ List getComponents(); @@ -91,7 +94,7 @@ public interface CompoundCRS extends CoordinateReferenceSystem { * @since 3.1 */ @UML(identifier="componentReferenceSystem", obligation=MANDATORY, specification=ISO_19111) - default List getSingleComponents() { + default List getFlattenedComponents() { var singles = new ArrayList(5); flatten(singles, new LinkedList<>()); // Linked list is cheap to construct and efficient with 0 or 1 element. return Collections.unmodifiableList(singles); diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/CompoundCS.java b/geoapi/src/main/java/org/opengis/referencing/crs/CompoundCS.java index 3893f3558..d4222d46c 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/CompoundCS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/CompoundCS.java @@ -17,6 +17,7 @@ */ package org.opengis.referencing.crs; +import java.io.Serializable; import org.opengis.metadata.Identifier; import org.opengis.referencing.cs.CoordinateSystem; import org.opengis.referencing.cs.CoordinateSystemAxis; @@ -32,14 +33,23 @@ * Implementers should override {@link CompoundCRS#getCoordinateSystem()} with their own implementation * for better performances or other characteristics such as WKT support. * + *

    Serialization

    + * Instances of this class are serializable if the wrapped CRS implementation is also serializable. + * * @author Martin Desruisseaux (Geomatys) * @version 3.1 * @since 3.1 */ -final class CompoundCS implements CoordinateSystem, Identifier { +final class CompoundCS implements CoordinateSystem, Identifier, Serializable { + /** + * For cross-version compatibility. + */ + private static final long serialVersionUID = 3782889810638117329L; + /** * The CRS provided by the implementer. */ + @SuppressWarnings("serial") // Whether the CRS is serializable is implementor's decision. private final CompoundCRS crs; /** diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/DerivedCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/DerivedCRS.java index 5022a63c4..53d97bd6a 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/DerivedCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/DerivedCRS.java @@ -19,6 +19,7 @@ import java.util.Map; import org.opengis.referencing.datum.Datum; +import org.opengis.referencing.datum.DatumEnsemble; import org.opengis.referencing.cs.CoordinateSystem; import org.opengis.referencing.operation.Conversion; import org.opengis.annotation.UML; @@ -34,7 +35,7 @@ * provided that the conditions in the right column are met: * * - * + * * * * @@ -43,22 +44,16 @@ * *
    Derived CRS typesDerived CRS types
    Type Conditions
    {@link ProjectedCRS} Base CRS is a {@link GeographicCRS} and conversion is a map projection.
    {@link GeodeticCRS} Base CRS is also a {@code GeodeticCRS}.
    {@link EngineeringCRS} Base CRS is a {@code GeodeticCRS}, {@code ProjectedCRS} or {@code EngineeringCRS}.
    * + *

    Projected CRS

    * In the special case where the CRS is derived from a base {@link GeographicCRS} by applying * a coordinate conversion known as a map projection to latitude and longitude ellipsoidal coordinate values, * the {@link ProjectedCRS} subtype should be used. Projected CRSs are modeled as a special case * of derived CRS because of their importance in geographic information. * - * @departure integration - * ISO 19111 defines a {@code SC_DerivedCRSType} code list with the following values: - * {@code geodetic}, {@code vertical}, {@code engineering} and {@code image}. - * But ISO 19162 takes a slightly different approach without such code list. - * Instead, ISO 19162 writes the derived CRS using the WKT keyword of the corresponding CRS type - * ({@code “GeodCRS”}, {@code “VertCRS”}, {@code “TimeCRS”} or {@code “EngCRS”}). - * GeoAPI follows a similar path by not providing a {@code DerivedCRSType} code list. - * Instead, we recommend to implement the corresponding interface as documented in the above table. - * Then, Java expressions like {@code (baseCRS instanceof FooCRS)} provides the same capability - * than the code list with more flexibility. For example, it allows to use a derived CRS of type “vertical” - * with API expecting an instance of {@code VerticalCRS}. + *

    Derived projected CRS

    + * In the special case where the CRS is derived from a base {@link ProjectedCRS}, + * the coordinate system of the derived CRS is not necessarily Cartesian. + * But the derived CRS still inherit the distortion characteristics of the base projected CRS. * * @author OGC Topic 2 (for abstract model and documentation) * @author Martin Desruisseaux (IRD, Geomatys) @@ -69,39 +64,61 @@ * @see CRSFactory#createDerivedCRS(Map, CoordinateReferenceSystem, Conversion, CoordinateSystem) */ @SuppressWarnings("removal") -@UML(identifier="SC_DerivedCRS", specification=ISO_19111, version=2007) +@UML(identifier="DerivedCRS", specification=ISO_19111, version=2007) public interface DerivedCRS extends GeneralDerivedCRS { /** - * Returns the base coordinate reference system. + * Returns the CRS that is the base for this derived CRS. + * This is the {@linkplain Conversion#getSourceCRS() source CRS} + * of the {@linkplain #getConversionFromBase() deriving conversion}. * - * @return the base coordinate reference system. + * @return the CRS that is the base for this derived CRS. */ @Override @UML(identifier="baseCRS", obligation=MANDATORY, specification=ISO_19111) SingleCRS getBaseCRS(); /** - * Returns the conversion from the base CRS to this CRS. + * Returns the conversion from the base CRS to this derived CRS. + * The source CRS of the conversion, if non null, shall be the {@linkplain #getBaseCRS() base CRS}. + * The target CRS of the conversion, if non-null, shall be this CRS. * - * @return the conversion from the base CRS. + * @return the conversion from the base CRS to this derived CRS. * * @departure rename - * "{@code conversion}" may be confusing as a method name - * since it does not indicate which CRS is the source or which is the target. - * The OGC 01-009 specification used the {@code toBase()} method name. - * By analogy with 01-009, GeoAPI defines a method name which contains the "{@code FromBase}" expression. + * Was {@code toBase} in OGC 01-009, {@code conversion} in ISO 19111:2007 + * and {@code derivingConversion} in ISO 19111:2019. By analogy with 01-009, + * GeoAPI defines a method name which contains the "{@code FromBase}" words + * for making clear which CRS is the source or which one is the target. */ @Override - @UML(identifier="conversion", obligation=MANDATORY, specification=ISO_19111) + @UML(identifier="derivingConversion", obligation=MANDATORY, specification=ISO_19111) Conversion getConversionFromBase(); /** - * Returns the same datum as the base CRS datum. + * Returns the same datum as the base CRS. + * This property may be null if the base CRS is related to an object + * identified only by a {@linkplain #getDatumEnsemble() datum ensemble}. * - * @return the datum of this derived CRS, which is the {@linkplain #getBaseCRS() base CRS} datum. + * @return the datum of the base CRS, or {@code null} if the base is related to + * an object identified only by a {@linkplain #getDatumEnsemble() datum ensemble}. */ @Override default Datum getDatum() { return getBaseCRS().getDatum(); } + + /** + * Returns the same datum ensemble as the base CRS. + * This property may be null if the base CRS is related to an object + * identified only by a single {@linkplain #getDatum() datum}. + * + * @return the datum ensemble of the base CRS, or {@code null} if the base is + * related to an object identified only by a single {@linkplain #getDatum() datum}. + * + * @since 3.1 + */ + @Override + default DatumEnsemble getDatumEnsemble() { + return getBaseCRS().getDatumEnsemble(); + } } diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/EngineeringCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/EngineeringCRS.java index 8fd3e6974..f8955941b 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/EngineeringCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/EngineeringCRS.java @@ -24,6 +24,7 @@ import static org.opengis.annotation.Obligation.*; import static org.opengis.annotation.Specification.*; +import org.opengis.referencing.datum.DatumEnsemble; /** @@ -46,29 +47,56 @@ * Transformation of coordinates from these moving engineering CRSs to planet-referenced * CRSs involves time-dependent coordinate operation parameters.

    * - *

    This type of CRS can be used with coordinate systems of type + *

    Permitted coordinate systems

    + * This type of CRS can be used with coordinate systems of type * {@link org.opengis.referencing.cs.AffineCS}, * {@link org.opengis.referencing.cs.CartesianCS}, * {@link org.opengis.referencing.cs.CylindricalCS}, * {@link org.opengis.referencing.cs.LinearCS}, * {@link org.opengis.referencing.cs.PolarCS}, * {@link org.opengis.referencing.cs.SphericalCS}, - * {@link org.opengis.referencing.cs.UserDefinedCS}.

    + * {@link org.opengis.referencing.cs.UserDefinedCS}. * * @author OGC Topic 2 (for abstract model and documentation) * @author Martin Desruisseaux (IRD, Geomatys) - * @version 3.0 + * @version 3.1 * @since 1.0 * * @see CRSAuthorityFactory#createEngineeringCRS(String) * @see CRSFactory#createEngineeringCRS(Map, EngineeringDatum, CoordinateSystem) */ -@UML(identifier="SC_EngineeringCRS", specification=ISO_19111, version=2007) +@UML(identifier="EngineeringCRS", specification=ISO_19111, version=2007) public interface EngineeringCRS extends SingleCRS { /** * Returns the datum, which shall be an engineering one. + * This property may be null if this CRS is related to an object + * identified only by a {@linkplain #getDatumEnsemble() datum ensemble}. + * + * @return the engineering datum, or {@code null} if this CRS is related to + * an object identified only by a {@linkplain #getDatumEnsemble() datum ensemble}. + * + * @condition Mandatory if the {@linkplain #getDatumEnsemble() datum ensemble} is not documented. */ @Override - @UML(identifier="datum", obligation=MANDATORY, specification=ISO_19111) + @UML(identifier="datum", obligation=CONDITIONAL, specification=ISO_19111) EngineeringDatum getDatum(); + + /** + * Returns the datum ensemble, which shall have engineering datum members. + * This property may be null if this CRS is related to an object + * identified only by a single {@linkplain #getDatum() datum}. + * + *

    The default implementation returns {@code null}.

    + * + * @return the datum ensemble, or {@code null} if this CRS is related + * to an object identified only by a single {@linkplain #getDatum() datum}. + * + * @condition Mandatory if the {@linkplain #getDatum() datum} is not documented. + * @since 3.1 + */ + @Override + @UML(identifier="datum", obligation=CONDITIONAL, specification=ISO_19111) + default DatumEnsemble getDatumEnsemble() { + return null; + } } diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/GeocentricCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/GeocentricCRS.java index 039fc3e35..64dfacd63 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/GeocentricCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/GeocentricCRS.java @@ -30,28 +30,28 @@ /** * A 3-dimensional CRS with the origin at the approximate centre of mass of the earth. - * A geocentric CRS deals with the earth's curvature by taking a 3-dimensional spatial view, which obviates - * the need to model the earth's curvature. + * A geocentric CRS deals with the earth's curvature by taking a 3-dimensional spatial view, which + * obviates the need to model the earth's curvature. * - *

    This type of CRS can be used with coordinate systems of type + *

    Permitted coordinate systems

    + * This type of CRS can be used with coordinate systems of type * {@link org.opengis.referencing.cs.CartesianCS Cartesian} or - * {@link org.opengis.referencing.cs.SphericalCS Spherical}.

    - * - * @departure historic - * This interface is kept conformant with the specification published in 2003. The 2007 revision - * of ISO 19111 removed the {@code SC_GeographicCRS} and {@code SC_GeocentricCRS} types, - * handling both using the {@code SC_GeodeticCRS} parent type. - * GeoAPI keeps them since the distinction between those two types is in wide use. + * {@link org.opengis.referencing.cs.SphericalCS Spherical}. * * @author OGC Topic 2 (for abstract model and documentation) * @author Martin Desruisseaux (IRD, Geomatys) - * @version 3.0 + * @version 3.1 * @since 1.0 * * @see CRSAuthorityFactory#createGeocentricCRS(String) * @see CRSFactory#createGeocentricCRS(Map, GeodeticDatum, CartesianCS) * @see CRSFactory#createGeographicCRS(Map, GeodeticDatum, EllipsoidalCS) + * + * @deprecated This type was defined in 2003 but removed in 2007. + * The ISO 19111 revision published in 2019 still excludes this type. + * The {@link GeodeticCRS} base type should be used instead. */ +@Deprecated(since="3.1", forRemoval=true) @UML(identifier="SC_GeocentricCRS", specification=ISO_19111, version=2003) public interface GeocentricCRS extends GeodeticCRS { /** diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/GeodeticCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/GeodeticCRS.java index 8b06966dd..e93dcfd62 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/GeodeticCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/GeodeticCRS.java @@ -17,6 +17,7 @@ */ package org.opengis.referencing.crs; +import org.opengis.referencing.datum.DatumEnsemble; import org.opengis.referencing.datum.GeodeticDatum; import org.opengis.annotation.UML; @@ -26,7 +27,10 @@ /** * A 2- or 3-dimensional CRS used over the whole planet or substantial parts of it. - * This type of CRS can be used with coordinate systems of type + * If the geodetic reference frame is dynamic then the geodetic CRS is dynamic, else it is static. + * + *

    Permitted coordinate systems

    + * This type of CRS can be used with coordinate systems of type * {@link org.opengis.referencing.cs.CartesianCS}, * {@link org.opengis.referencing.cs.SphericalCS} or * {@link org.opengis.referencing.cs.EllipsoidalCS}. @@ -37,12 +41,38 @@ * @version 3.1 * @since 2.1 */ -@UML(identifier="SC_GeodeticCRS", specification=ISO_19111, version=2007) +@UML(identifier="GeodeticCRS", specification=ISO_19111) public interface GeodeticCRS extends SingleCRS { /** - * Returns the datum, which shall be geodetic. + * Returns the reference frame, which shall be geodetic. + * This property may be null if this CRS is related to an object + * identified only by a {@linkplain #getDatumEnsemble() datum ensemble}. + * + * @return the reference frame, or {@code null} if this CRS is related to + * an object identified only by a {@linkplain #getDatumEnsemble() datum ensemble}. + * + * @condition Mandatory if the {@linkplain #getDatumEnsemble() datum ensemble} is not documented. */ @Override - @UML(identifier="datum", obligation=MANDATORY, specification=ISO_19111) + @UML(identifier="datum", obligation=CONDITIONAL, specification=ISO_19111) GeodeticDatum getDatum(); + + /** + * Returns the datum ensemble, which shall have geodetic datum members. + * This property may be null if this CRS is related to an object + * identified only by a single {@linkplain #getDatum() datum}. + * + *

    The default implementation returns {@code null}.

    + * + * @return the datum ensemble, or {@code null} if this CRS is related + * to an object identified only by a single {@linkplain #getDatum() datum}. + * + * @condition Mandatory if the {@linkplain #getDatum() datum} is not documented. + * @since 3.1 + */ + @Override + @UML(identifier="datum", obligation=CONDITIONAL, specification=ISO_19111) + default DatumEnsemble getDatumEnsemble() { + return null; + } } diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/GeographicCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/GeographicCRS.java index a48de9b27..1590d7d63 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/GeographicCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/GeographicCRS.java @@ -19,6 +19,7 @@ import java.util.Map; import org.opengis.referencing.cs.EllipsoidalCS; +import org.opengis.referencing.datum.Ellipsoid; import org.opengis.referencing.datum.GeodeticDatum; import org.opengis.annotation.UML; @@ -35,33 +36,23 @@ *

    A geographic CRS is not suitable for mapmaking on a planar surface, * because it describes geometry on a curved surface. * It is impossible to represent such geometry in a Euclidean plane without introducing distortions. - * The need to control these distortions has given rise to the development of the science of - * {@linkplain org.opengis.referencing.operation.Projection map projections}.

    + * The need to control these distortions has given rise to the development of {@link ProjectedCRS}s.

    * - *

    This type of CRS can be used with coordinate systems of type - * {@link org.opengis.referencing.cs.EllipsoidalCS}.

    + *

    The {@link GeodeticDatum} associated to this CRS must have an {@link Ellipsoid}. + * I.e., the ellipsoid is generally optional but become mandatory in the context of {@code GeographicCRS}.

    * - * @departure constraint - * This interface is kept conformant with the specification published in 2003. The 2007 revision - * of ISO 19111 removed the {@code SC_GeographicCRS} and {@code SC_GeocentricCRS} types, - * handling both using the {@code SC_GeodeticCRS} parent type. GeoAPI keeps them for two reasons: - *
      - *
    • The distinction between those two types is in wide use.
    • - *
    • A distinct geographic type allows GeoAPI to restrict the coordinate system type to {@code EllipsoidalCS}. - * ISO 19111 uses a {@code union} for expressing this restriction at the {@code SC_GeodeticCRS} level, but - * the Java language does not provide such construct. A distinct geographic type is one way to achieve the - * same goal.
    • - *
    + *

    Permitted coordinate systems

    + * This type of CRS can be used with coordinate systems of type {@link EllipsoidalCS} only. * * @author OGC Topic 2 (for abstract model and documentation) * @author Martin Desruisseaux (IRD, Geomatys) - * @version 3.0 + * @version 3.1 * @since 1.0 * * @see CRSAuthorityFactory#createGeographicCRS(String) * @see CRSFactory#createGeographicCRS(Map, GeodeticDatum, EllipsoidalCS) */ -@UML(identifier="SC_GeographicCRS", specification=ISO_19111, version=2003) +@UML(identifier="GeographicCRS", specification=ISO_19111) public interface GeographicCRS extends GeodeticCRS { /** * Returns the coordinate system, which shall be ellipsoidal. diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/ParametricCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/ParametricCRS.java index dc3993cde..545c438b5 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/ParametricCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/ParametricCRS.java @@ -19,16 +19,17 @@ import java.util.Map; import org.opengis.referencing.cs.ParametricCS; +import org.opengis.referencing.datum.DatumEnsemble; import org.opengis.referencing.datum.ParametricDatum; import org.opengis.annotation.UML; -import static org.opengis.annotation.Obligation.MANDATORY; -import static org.opengis.annotation.Specification.ISO_19111_2; +import static org.opengis.annotation.Obligation.*; +import static org.opengis.annotation.Specification.ISO_19111; /** * A 1-dimensional CRS which uses parameter values or functions. - * A coordinate reference system shall be of the parametric type if a physical or material + * A CRS shall be of the parametric type if a physical or material * property or function is used as the dimension. * The values or functions can vary monotonically with height. * @@ -37,18 +38,19 @@ * density (isopycnals) in oceanographic applications. *
* - *

This type of CRS can be used with coordinate systems of type - * {@link org.opengis.referencing.cs.ParametricCS}.

+ *

Permitted coordinate systems

+ * This type of CRS can be used with coordinate systems of type {@link ParametricCS} only. * * @author OGC Topic 2 (for abstract model and documentation) * @author Johann Sorel (Geomatys) + * @author Martin Desruisseaux (Geomatys) * @version 3.1 * @since 3.1 * * @see CRSAuthorityFactory#createParametricCRS(String) * @see CRSFactory#createParametricCRS(Map, ParametricDatum, ParametricCS) */ -@UML(identifier="SC_ParametricCRS", specification=ISO_19111_2) +@UML(identifier="ParametricCRS", specification=ISO_19111) public interface ParametricCRS extends SingleCRS { /** * Returns the coordinate system, which shall be parametric. @@ -56,13 +58,38 @@ public interface ParametricCRS extends SingleCRS { * @return the parametric coordinate system. */ @Override - @UML(identifier="coordinateSystem", obligation=MANDATORY, specification=ISO_19111_2) + @UML(identifier="coordinateSystem", obligation=MANDATORY, specification=ISO_19111) ParametricCS getCoordinateSystem(); /** * Returns the datum, which shall be parametric. + * This property may be null if this CRS is related to an object + * identified only by a {@linkplain #getDatumEnsemble() datum ensemble}. + * + * @return the parametric datum, or {@code null} if this CRS is related to + * an object identified only by a {@linkplain #getDatumEnsemble() datum ensemble}. + * + * @condition Mandatory if the {@linkplain #getDatumEnsemble() datum ensemble} is not documented. */ @Override - @UML(identifier="datum", obligation=MANDATORY, specification=ISO_19111_2) + @UML(identifier="datum", obligation=CONDITIONAL, specification=ISO_19111) ParametricDatum getDatum(); + + /** + * Returns the datum ensemble, which shall have parametric datum members. + * This property may be null if this CRS is related to an object + * identified only by a single {@linkplain #getDatum() datum}. + * + *

The default implementation returns {@code null}.

+ * + * @return the datum ensemble, or {@code null} if this CRS is related + * to an object identified only by a single {@linkplain #getDatum() datum}. + * + * @condition Mandatory if the {@linkplain #getDatum() datum} is not documented. + */ + @Override + @UML(identifier="datum", obligation=CONDITIONAL, specification=ISO_19111) + default DatumEnsemble getDatumEnsemble() { + return null; + } } diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/ProjectedCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/ProjectedCRS.java index 34fbd4d73..36bb1d50f 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/ProjectedCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/ProjectedCRS.java @@ -19,6 +19,7 @@ import java.util.Map; import org.opengis.referencing.cs.CartesianCS; +import org.opengis.referencing.datum.DatumEnsemble; import org.opengis.referencing.datum.GeodeticDatum; import org.opengis.referencing.operation.Conversion; import org.opengis.referencing.operation.Projection; @@ -34,8 +35,8 @@ * Distortion correction is commonly applied to calculated bearings and distances * to produce values that are a close match to actual field values. * - *

This type of CRS can be used with coordinate systems of type - * {@link org.opengis.referencing.cs.CartesianCS}.

+ *

Permitted coordinate systems

+ * This type of CRS can be used with coordinate systems of type {@link CartesianCS} only. * * @author OGC Topic 2 (for abstract model and documentation) * @author Martin Desruisseaux (IRD, Geomatys) @@ -45,20 +46,24 @@ * @see CRSAuthorityFactory#createProjectedCRS(String) * @see CRSFactory#createProjectedCRS(Map, GeographicCRS, Conversion, CartesianCS) */ -@UML(identifier="SC_ProjectedCRS", specification=ISO_19111, version=2007) +@UML(identifier="ProjectedCRS", specification=ISO_19111) public interface ProjectedCRS extends DerivedCRS { /** - * Returns the base coordinate reference system, which must be geographic. + * Returns the CRS that is the base for this projected CRS. + * This is the {@linkplain Conversion#getSourceCRS() source CRS} + * of the {@linkplain #getConversionFromBase() deriving conversion}. * - * @return the base geographic CRS. + * @return the CRS that is the base for this projected CRS. */ @Override GeographicCRS getBaseCRS(); /** - * Returns the map projection from the base CRS to this CRS. + * Returns the map projection from the base CRS to this projected CRS. + * The source CRS of the conversion, if non null, shall be the {@linkplain #getBaseCRS() base CRS}. + * The target CRS of the conversion, if non-null, shall be this CRS. * - * @return the conversion from the {@linkplain #getBaseCRS() base CRS} to this projected CRS. + * @return the map projection from the base CRS to this projected CRS. */ @Override Projection getConversionFromBase(); @@ -68,20 +73,38 @@ public interface ProjectedCRS extends DerivedCRS { * In the 3D case the ellipsoidal height from the base CRS * is retained to form a three-dimensional Cartesian coordinate system. * - * @return the Cartesian coordinate system. + * @return the Cartesian coordinate system associated to this projected CRS. */ @Override @UML(identifier="coordinateSystem", obligation=MANDATORY, specification=ISO_19111) CartesianCS getCoordinateSystem(); /** - * Returns the same datum as the base CRS datum. + * Returns the same datum as the base geodetic CRS. + * This property may be null if the base CRS is related to an object + * identified only by a {@linkplain #getDatumEnsemble() datum ensemble}. * - * @return the datum of this projected CRS, which is the {@linkplain #getBaseCRS() base CRS} datum. + * @return the datum of the base geodetic CRS, or {@code null} if the base is related + * to an object identified only by a {@linkplain #getDatumEnsemble() datum ensemble}. */ @Override @UML(identifier="datum", obligation=MANDATORY, specification=ISO_19111) default GeodeticDatum getDatum() { return getBaseCRS().getDatum(); } + + /** + * Returns the same datum ensemble as the base geodetic CRS. + * This property may be null if the base CRS is related to an object + * identified only by a single {@linkplain #getDatum() datum}. + * + * @return the datum ensemble of the base geodetic CRS, or {@code null} if the base + * is related to an object identified only by a single {@linkplain #getDatum() datum}. + * + * @since 3.1 + */ + @Override + default DatumEnsemble getDatumEnsemble() { + return getBaseCRS().getDatumEnsemble(); + } } diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/SingleCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/SingleCRS.java index 36dcd9849..696aea4c8 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/SingleCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/SingleCRS.java @@ -18,6 +18,7 @@ package org.opengis.referencing.crs; import org.opengis.referencing.datum.Datum; +import org.opengis.referencing.datum.DatumEnsemble; import org.opengis.referencing.cs.CoordinateSystem; import org.opengis.annotation.UML; import org.opengis.annotation.Classifier; @@ -29,12 +30,13 @@ /** * Base type of CRS related to an object by a datum or datum ensemble. - * For {@linkplain org.opengis.referencing.datum.GeodeticDatum geodetic} - * and {@linkplain org.opengis.referencing.datum.VerticalDatum vertical} reference frame, - * the object will be the Earth or another celestial body. + * The object will generally, but not necessarily, be the Earth. It can be identified either + * by a {@linkplain #getDatum() datum} or a {@linkplain #getDatumEnsemble() datum ensemble}. + * At least one of those two properties shall be present. * *

The valid coordinate system type and the datum type are constrained by the CRS type. - * For example, {@code GeographicCRS} can be associated only to {@code EllipsoidalCS} and {@code GeodeticDatum}. + * For example, {@link GeographicCRS} can be associated only to {@code GeodeticReferenceFrame} + * (a specialization of {@code Datum}) and {@code EllipsoidalCS}. * The constraints are documented in the Javadoc of sub-interfaces.

* * @author OGC Topic 2 (for abstract model and documentation) @@ -64,19 +66,49 @@ public interface SingleCRS extends CoordinateReferenceSystem { * Returns the datum associated directly or indirectly to this CRS. * In the case of {@link DerivedCRS}, this method returns the * datum of the {@linkplain DerivedCRS#getBaseCRS() base CRS}. + * This property may be null if this CRS is related to an object + * identified only by a {@linkplain #getDatumEnsemble() datum ensemble}. * *

A datum specifies the relationship of a coordinate system to the object, thus ensuring that the abstract * mathematical concept “coordinate system” can be applied to the practical problem of describing positions of * features on or near the planet's surface by means of coordinates. * The object will generally, but not necessarily, be the Earth. - * For certain coordinate reference systems, the object may be a moving platform.

+ * For certain CRSs, the object may be a moving platform.

* - * @return the datum associated directly or indirectly to this CRS. + * @return the datum, or {@code null} if this CRS is related to an object + * identified only by a {@linkplain #getDatumEnsemble() datum ensemble}. * * @departure easeOfUse * The ISO specification declares the datum as absent when the association is indirect. * GeoAPI recommends to follow the link to the base CRS for users convenience. + * + * @condition Mandatory if the {@linkplain #getDatumEnsemble() datum ensemble} is not documented. */ @UML(identifier="datum", obligation=CONDITIONAL, specification=ISO_19111) Datum getDatum(); + + /** + * Returns the datum ensemble associated directly or indirectly to this CRS. + * In the case of {@link DerivedCRS}, this method returns the datum ensemble + * of the {@linkplain DerivedCRS#getBaseCRS() base CRS}. + * This property may be null if this CRS is related to an object + * identified only by a single {@linkplain #getDatum() datum}. + * + *

The default implementation returns {@code null}.

+ * + * @return the datum ensemble, or {@code null} if this CRS is related + * to an object identified only by a single {@linkplain #getDatum() datum}. + * + * @condition Mandatory if the {@linkplain #getDatum() datum} is not documented. + * @since 3.1 + */ + @UML(identifier="datumEnsemble", obligation=CONDITIONAL, specification=ISO_19111) + default DatumEnsemble getDatumEnsemble() { + /* + * API design note: we cannot use `Optional.empty()` because the use of `Optional>` + * as the return type prevents sub-interfaces to specialize the `` part with a more specific type. + * Anyway, this attribute is not exactly optional but conditional. + */ + return null; + } } diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/TemporalCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/TemporalCRS.java index 2243a9412..441edd527 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/TemporalCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/TemporalCRS.java @@ -19,6 +19,7 @@ import java.util.Map; import org.opengis.referencing.cs.TimeCS; +import org.opengis.referencing.datum.DatumEnsemble; import org.opengis.referencing.datum.TemporalDatum; import org.opengis.annotation.UML; @@ -31,18 +32,18 @@ * Any CRS can be associate with a temporal CRS to form a spatio-temporal {@link CompoundCRS}. * More than one temporal CRS may be included if these axes represent different time quantities. * - *

This type of CRS can be used with coordinate systems of type - * {@link org.opengis.referencing.cs.TimeCS}.

+ *

Permitted coordinate systems

+ * This type of CRS can be used with coordinate systems of type {@link TimeCS} only. * * @author OGC Topic 2 (for abstract model and documentation) * @author Martin Desruisseaux (IRD, Geomatys) - * @version 3.0 + * @version 3.1 * @since 1.0 * * @see CRSAuthorityFactory#createTemporalCRS(String) * @see CRSFactory#createTemporalCRS(Map, TemporalDatum, TimeCS) */ -@UML(identifier="SC_TemporalCRS", specification=ISO_19111) +@UML(identifier="TemporalCRS", specification=ISO_19111) public interface TemporalCRS extends SingleCRS { /** * Returns the coordinate system, which shall be temporal. @@ -55,8 +56,34 @@ public interface TemporalCRS extends SingleCRS { /** * Returns the datum, which shall be temporal. + * This property may be null if this CRS is related to an object + * identified only by a {@linkplain #getDatumEnsemble() datum ensemble}. + * + * @return the temporal datum, or {@code null} if this CRS is related to + * an object identified only by a {@linkplain #getDatumEnsemble() datum ensemble}. + * + * @condition Mandatory if the {@linkplain #getDatumEnsemble() datum ensemble} is not documented. */ @Override - @UML(identifier="datum", obligation=MANDATORY, specification=ISO_19111) + @UML(identifier="datum", obligation=CONDITIONAL, specification=ISO_19111) TemporalDatum getDatum(); + + /** + * Returns the datum ensemble, which shall have temporal datum members. + * This property may be null if this CRS is related to an object + * identified only by a single {@linkplain #getDatum() datum}. + * + *

The default implementation returns {@code null}.

+ * + * @return the datum ensemble, or {@code null} if this CRS is related + * to an object identified only by a single {@linkplain #getDatum() datum}. + * + * @condition Mandatory if the {@linkplain #getDatum() datum} is not documented. + * @since 3.1 + */ + @Override + @UML(identifier="datum", obligation=CONDITIONAL, specification=ISO_19111) + default DatumEnsemble getDatumEnsemble() { + return null; + } } diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/VerticalCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/VerticalCRS.java index 6fe6eff17..a63f6a6fc 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/VerticalCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/VerticalCRS.java @@ -20,6 +20,7 @@ import java.util.Map; import org.opengis.referencing.cs.VerticalCS; import org.opengis.referencing.datum.VerticalDatum; +import org.opengis.referencing.datum.DatumEnsemble; import org.opengis.annotation.UML; import static org.opengis.annotation.Obligation.*; @@ -35,18 +36,18 @@ * Ellipsoidal heights cannot exist independently, but only as inseparable part of a 3D coordinate tuple * defined in a geographic or projected 3D CRS.

* - *

This type of CRS can be used with coordinate systems of type - * {@link org.opengis.referencing.cs.VerticalCS}.

+ *

Permitted coordinate systems

+ * This type of CRS can be used with coordinate systems of type {@link VerticalCS} only. * * @author OGC Topic 2 (for abstract model and documentation) * @author Martin Desruisseaux (IRD, Geomatys) - * @version 3.0 + * @version 3.1 * @since 1.0 * * @see CRSAuthorityFactory#createVerticalCRS(String) * @see CRSFactory#createVerticalCRS(Map, VerticalDatum, VerticalCS) */ -@UML(identifier="SC_VerticalCRS", specification=ISO_19111, version=2007) +@UML(identifier="VerticalCRS", specification=ISO_19111) public interface VerticalCRS extends SingleCRS { /** * Returns the coordinate system, which shall be vertical. @@ -58,9 +59,35 @@ public interface VerticalCRS extends SingleCRS { VerticalCS getCoordinateSystem(); /** - * Returns the datum, which must be vertical. + * Returns the reference frame, which shall be vertical. + * This property may be null if this CRS is related to an object + * identified only by a {@linkplain #getDatumEnsemble() datum ensemble}. + * + * @return the reference frame, or {@code null} if this CRS is related to + * an object identified only by a {@linkplain #getDatumEnsemble() datum ensemble}. + * + * @condition Mandatory if the {@linkplain #getDatumEnsemble() datum ensemble} is not documented. */ @Override - @UML(identifier="datum", obligation=MANDATORY, specification=ISO_19111) + @UML(identifier="datum", obligation=CONDITIONAL, specification=ISO_19111) VerticalDatum getDatum(); + + /** + * Returns the datum ensemble, which shall have vertical datum members. + * This property may be null if this CRS is related to an object + * identified only by a single {@linkplain #getDatum() datum}. + * + *

The default implementation returns {@code null}.

+ * + * @return the datum ensemble, or {@code null} if this CRS is related + * to an object identified only by a single {@linkplain #getDatum() datum}. + * + * @condition Mandatory if the {@linkplain #getDatum() datum} is not documented. + * @since 3.1 + */ + @Override + @UML(identifier="datum", obligation=CONDITIONAL, specification=ISO_19111) + default DatumEnsemble getDatumEnsemble() { + return null; + } } diff --git a/geoapi/src/main/java/org/opengis/referencing/cs/CSAuthorityFactory.java b/geoapi/src/main/java/org/opengis/referencing/cs/CSAuthorityFactory.java index 124ab316d..84d1539de 100644 --- a/geoapi/src/main/java/org/opengis/referencing/cs/CSAuthorityFactory.java +++ b/geoapi/src/main/java/org/opengis/referencing/cs/CSAuthorityFactory.java @@ -32,7 +32,7 @@ * Creates {@linkplain CoordinateSystem coordinate systems} using authority codes. * External authorities are used to manage definitions of objects used in this interface. * The definitions of these objects are referenced using code strings. - * A commonly used authority is EPSG. + * A commonly used authority is the EPSG geodetic registry. * *

Default methods

* All {@code create(…)} methods in this interface are optional. diff --git a/geoapi/src/main/java/org/opengis/referencing/cs/package-info.java b/geoapi/src/main/java/org/opengis/referencing/cs/package-info.java index 6df43837e..78bae7c70 100644 --- a/geoapi/src/main/java/org/opengis/referencing/cs/package-info.java +++ b/geoapi/src/main/java/org/opengis/referencing/cs/package-info.java @@ -24,7 +24,7 @@ * The number of axes is the dimension of the coordinate space. Axis order is significant. * *

One {@link org.opengis.referencing.cs.CoordinateSystem} instance may be used by multiple - * {@link org.opengis.referencing.crs.CoordinateReferenceSystem} (CRS) instances. + * {@link org.opengis.referencing.crs.CoordinateReferenceSystem} (CRS) instances. * The {@linkplain org.opengis.geometry.DirectPosition#getDimension() number of coordinates} in a coordinate tuple * shall be equal to the {@linkplain org.opengis.referencing.cs.CoordinateSystem#getDimension() number of coordinate axes} * in the coordinate system. @@ -36,17 +36,16 @@ * Certain subtypes of coordinate system shall be used only with specific subtypes of coordinate reference system. * The restrictions are documented in the javadoc of each CRS subtype. * - *

ISO 19111 defines some coordinate system unions in addition to the coordinate system types. - * Each union enumerates the coordinate system types that can be associated to a CRS type. - * GeoAPI does not define those unions because they have no direct equivalence in the Java language.

+ *

Coordinate system types should not be confused with coordinate system unions. + * The latter look similar to CS types, but do not imply a specific set of mathematical rules. + * A CS union is only an enumeration of the CS types that can be associated to a + * given CRS type. For example, ISO 19111 defines {@code GeodeticCS} as the enumeration of the + * types of CS that can be associated to a {@code GeodeticCRS}. + * Since unions are not available in Java (they are available in some other languages such as C++), + * GeoAPI replaces them by Javadoc. All CS defined in this packages are types.

* - * @departure constraint - * ISO 19111 defines {@code GeodeticCS} and {@code EngineeringCS} unions. - * However, the {@code union} construct found in some languages like C/C++ is not available in Java. - * For each union, a different approach has been applied and documented in the {@code org.opengis.referencing.cs} - * package. - * - * @author Martin Desruisseaux (IRD) + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.1 * @since 1.0 */ diff --git a/geoapi/src/main/java/org/opengis/referencing/datum/Datum.java b/geoapi/src/main/java/org/opengis/referencing/datum/Datum.java index fc0e90955..421152b51 100644 --- a/geoapi/src/main/java/org/opengis/referencing/datum/Datum.java +++ b/geoapi/src/main/java/org/opengis/referencing/datum/Datum.java @@ -31,8 +31,7 @@ /** - * Specifies the relationship of a coordinate system to the earth, - * thus creating a coordinate reference system. + * Specifies the relationship of a coordinate system to an object. * For {@linkplain org.opengis.referencing.crs.GeocentricCRS geodetic} and * {@linkplain org.opengis.referencing.crs.VerticalCRS vertical} coordinate reference systems, * the datum relates the coordinate system to the Earth. With other types of coordinate reference systems, diff --git a/geoapi/src/main/java/org/opengis/referencing/datum/DatumAuthorityFactory.java b/geoapi/src/main/java/org/opengis/referencing/datum/DatumAuthorityFactory.java index c0e1888fe..d28e821bc 100644 --- a/geoapi/src/main/java/org/opengis/referencing/datum/DatumAuthorityFactory.java +++ b/geoapi/src/main/java/org/opengis/referencing/datum/DatumAuthorityFactory.java @@ -31,7 +31,7 @@ * Creates datum objects using authority codes. * External authorities are used to manage definitions of objects used in this interface. * The definitions of these objects are referenced using code strings. - * A commonly used authority is EPSG. + * A commonly used authority is the EPSG geodetic registry. * *

Default methods

* All {@code create(…)} methods in this interface are optional. diff --git a/geoapi/src/main/java/org/opengis/referencing/datum/DatumEnsemble.java b/geoapi/src/main/java/org/opengis/referencing/datum/DatumEnsemble.java new file mode 100644 index 000000000..e6a9dde90 --- /dev/null +++ b/geoapi/src/main/java/org/opengis/referencing/datum/DatumEnsemble.java @@ -0,0 +1,38 @@ +/* + * GeoAPI - Java interfaces for OGC/ISO standards + * Copyright © 2003-2024 Open Geospatial Consortium, Inc. + * http://www.geoapi.org + * + * Licensed 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.opengis.referencing.datum; + +import org.opengis.referencing.IdentifiedObject; +import org.opengis.annotation.UML; + +import static org.opengis.annotation.Specification.*; + + +/** + * + * @author OGC Topic 2 (for abstract model and documentation) + * @author Martin Desruisseaux (IRD, Geomatys) + * @version 3.1 + * + * @param the type of datum contained in this ensemble. + * + * @since 3.1 + */ +@UML(identifier="DatumEnsemble", specification=ISO_19111) +public interface DatumEnsemble extends IdentifiedObject { +} diff --git a/geoapi/src/main/java/org/opengis/referencing/operation/CoordinateOperationAuthorityFactory.java b/geoapi/src/main/java/org/opengis/referencing/operation/CoordinateOperationAuthorityFactory.java index f8a43802d..7db4f1a6b 100644 --- a/geoapi/src/main/java/org/opengis/referencing/operation/CoordinateOperationAuthorityFactory.java +++ b/geoapi/src/main/java/org/opengis/referencing/operation/CoordinateOperationAuthorityFactory.java @@ -29,9 +29,8 @@ /** - * Creates coordinate transformation objects from codes. The codes are maintained by an - * external authority. A commonly used authority is EPSG, - * which is also used in the GeoTIFF standard. + * Creates coordinate transformation objects from codes. The codes are maintained by an external authority. + * A commonly used authority is the EPSG geodetic registry. * * @author Martin Desruisseaux (IRD) * @version 3.0 diff --git a/geoapi/src/main/resources/org/opengis/annotation/class-index.properties b/geoapi/src/main/resources/org/opengis/annotation/class-index.properties index 2fd744c00..8cf4c6366 100644 --- a/geoapi/src/main/resources/org/opengis/annotation/class-index.properties +++ b/geoapi/src/main/resources/org/opengis/annotation/class-index.properties @@ -107,6 +107,8 @@ DQ_ThematicClassificationCorrectness=org.opengis.metadata.quality.ThematicClassi DQ_TopologicalConsistency=org.opengis.metadata.quality.TopologicalConsistency DS_AssociationTypeCode=org.opengis.metadata.identification.AssociationType DS_InitiativeTypeCode=org.opengis.metadata.identification.InitiativeType +DatumEnsemble=org.opengis.referencing.datum.DatumEnsemble +DerivedCRS=org.opengis.referencing.crs.DerivedCRS EX_BoundingPolygon=org.opengis.metadata.extent.BoundingPolygon EX_Extent=org.opengis.metadata.extent.Extent EX_GeographicBoundingBox=org.opengis.metadata.extent.GeographicBoundingBox @@ -115,6 +117,9 @@ EX_GeographicExtent=org.opengis.metadata.extent.GeographicExtent EX_SpatialTemporalExtent=org.opengis.metadata.extent.SpatialTemporalExtent EX_TemporalExtent=org.opengis.metadata.extent.TemporalExtent EX_VerticalExtent=org.opengis.metadata.extent.VerticalExtent +EngineeringCRS=org.opengis.referencing.crs.EngineeringCRS +GeodeticCRS=org.opengis.referencing.crs.GeodeticCRS +GeographicCRS=org.opengis.referencing.crs.GeographicCRS IdentifiedObject=org.opengis.referencing.IdentifiedObject LE_Algorithm=org.opengis.metadata.lineage.Algorithm LE_NominalResolution=org.opengis.metadata.lineage.NominalResolution @@ -224,20 +229,15 @@ MI_TransferFunctionTypeCode=org.opengis.metadata.content.TransferFunctionType MI_TriggerCode=org.opengis.metadata.acquisition.Trigger ObjectDomain=org.opengis.referencing.ObjectDomain PT_FreeText=org.opengis.util.InternationalString +ParametricCRS=org.opengis.referencing.crs.ParametricCRS +ProjectedCRS=org.opengis.referencing.crs.ProjectedCRS QE_Usability=org.opengis.metadata.quality.Usability RS_Identifier=org.opengis.referencing.ReferenceIdentifier RS_ReferenceSystem=org.opengis.referencing.ReferenceSystem SC_CompoundCRS=org.opengis.referencing.crs.CompoundCRS -SC_DerivedCRS=org.opengis.referencing.crs.DerivedCRS -SC_EngineeringCRS=org.opengis.referencing.crs.EngineeringCRS SC_GeneralDerivedCRS=org.opengis.referencing.crs.GeneralDerivedCRS SC_GeocentricCRS=org.opengis.referencing.crs.GeocentricCRS -SC_GeodeticCRS=org.opengis.referencing.crs.GeodeticCRS -SC_GeographicCRS=org.opengis.referencing.crs.GeographicCRS SC_ImageCRS=org.opengis.referencing.crs.ImageCRS -SC_ProjectedCRS=org.opengis.referencing.crs.ProjectedCRS -SC_TemporalCRS=org.opengis.referencing.crs.TemporalCRS -SC_VerticalCRS=org.opengis.referencing.crs.VerticalCRS SV_CoupledResource=org.opengis.metadata.identification.CoupledResource SV_CouplingType=org.opengis.metadata.identification.CouplingType SV_OperationChainMetadata=org.opengis.metadata.identification.OperationChainMetadata @@ -245,3 +245,5 @@ SV_OperationMetadata=org.opengis.metadata.identification.OperationMetadata SV_ParameterDirection=org.opengis.parameter.ParameterDirection SV_ServiceIdentification=org.opengis.metadata.identification.ServiceIdentification SingleCRS=org.opengis.referencing.crs.SingleCRS +TemporalCRS=org.opengis.referencing.crs.TemporalCRS +VerticalCRS=org.opengis.referencing.crs.VerticalCRS diff --git a/geoapi/src/shared/java/org/opengis/geoapi/Content.java b/geoapi/src/shared/java/org/opengis/geoapi/Content.java index ca930a289..15523ae9e 100644 --- a/geoapi/src/shared/java/org/opengis/geoapi/Content.java +++ b/geoapi/src/shared/java/org/opengis/geoapi/Content.java @@ -115,6 +115,7 @@ public enum Content { org.opengis.metadata.identification .ServiceIdentification .class, org.opengis.referencing .ReferenceSystem .class, // Depends on Extent. org.opengis.referencing.datum .Datum .class, + org.opengis.referencing.datum .DatumEnsemble .class, org.opengis.referencing.cs .CoordinateSystemAxis .class, org.opengis.referencing.cs .CoordinateSystem .class, org.opengis.referencing.crs .CoordinateReferenceSystem .class, diff --git a/geoapi/src/shared/java/org/opengis/geoapi/NameSpaces.java b/geoapi/src/shared/java/org/opengis/geoapi/NameSpaces.java index 61e0a3692..b2848a771 100644 --- a/geoapi/src/shared/java/org/opengis/geoapi/NameSpaces.java +++ b/geoapi/src/shared/java/org/opengis/geoapi/NameSpaces.java @@ -149,6 +149,7 @@ public QName name(final Class type, final Map components = crs.getSingleComponents(); + List components = crs.getFlattenedComponents(); assertEquals(3, components.size()); verifyAxes(components.get(0).getCoordinateSystem(), "x0:0", "x0:1"); verifyAxes(components.get(1).getCoordinateSystem(), "x1:2"); From 50d85a22f9c431bc3fc8173a864cb4609c1ca32b Mon Sep 17 00:00:00 2001 From: Martin Desruisseaux Date: Thu, 21 Mar 2024 18:53:05 +0100 Subject: [PATCH 05/20] ISO 19111 upgrade: first try to define a mapping between the temporal coordinate system defined by the Standard, and the temporal object defined in the `java.time` package. We try to avoid duplicating the standard Java library. --- .../opengis/referencing/crs/DerivedCRS.java | 2 +- .../opengis/referencing/cs/ParametricCS.java | 2 +- .../org/opengis/referencing/cs/TimeCS.java | 47 ++- .../org/opengis/referencing/cs/TimeUnit.java | 277 ++++++++++++++++++ .../opengis/referencing/cs/package-info.java | 28 +- .../opengis/annotation/class-index.properties | 2 +- .../java/org/opengis/geoapi/NameSpaces.java | 1 + 7 files changed, 341 insertions(+), 18 deletions(-) create mode 100644 geoapi/src/main/java/org/opengis/referencing/cs/TimeUnit.java diff --git a/geoapi/src/main/java/org/opengis/referencing/crs/DerivedCRS.java b/geoapi/src/main/java/org/opengis/referencing/crs/DerivedCRS.java index 53d97bd6a..b939cb923 100644 --- a/geoapi/src/main/java/org/opengis/referencing/crs/DerivedCRS.java +++ b/geoapi/src/main/java/org/opengis/referencing/crs/DerivedCRS.java @@ -64,7 +64,7 @@ * @see CRSFactory#createDerivedCRS(Map, CoordinateReferenceSystem, Conversion, CoordinateSystem) */ @SuppressWarnings("removal") -@UML(identifier="DerivedCRS", specification=ISO_19111, version=2007) +@UML(identifier="DerivedCRS", specification=ISO_19111) public interface DerivedCRS extends GeneralDerivedCRS { /** * Returns the CRS that is the base for this derived CRS. diff --git a/geoapi/src/main/java/org/opengis/referencing/cs/ParametricCS.java b/geoapi/src/main/java/org/opengis/referencing/cs/ParametricCS.java index e55c43822..ed5c8b3f6 100644 --- a/geoapi/src/main/java/org/opengis/referencing/cs/ParametricCS.java +++ b/geoapi/src/main/java/org/opengis/referencing/cs/ParametricCS.java @@ -24,7 +24,7 @@ /** - * A 1-dimensional coordinate system containing a single axis. + * A 1-dimensional coordinate system in which a physical property or function is used as the dimension. * This coordinate system uses parameter values or functions to describe the position of a point. * *

This type of CS can be used by coordinate reference systems of type diff --git a/geoapi/src/main/java/org/opengis/referencing/cs/TimeCS.java b/geoapi/src/main/java/org/opengis/referencing/cs/TimeCS.java index 857639b84..fbce7aa8a 100644 --- a/geoapi/src/main/java/org/opengis/referencing/cs/TimeCS.java +++ b/geoapi/src/main/java/org/opengis/referencing/cs/TimeCS.java @@ -1,6 +1,6 @@ /* * GeoAPI - Java interfaces for OGC/ISO standards - * Copyright © 2004-2023 Open Geospatial Consortium, Inc. + * Copyright © 2004-2024 Open Geospatial Consortium, Inc. * http://www.geoapi.org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,25 +18,62 @@ package org.opengis.referencing.cs; import java.util.Map; +import java.time.temporal.ChronoUnit; +import java.time.temporal.TemporalUnit; +import javax.measure.quantity.Time; import org.opengis.annotation.UML; + import static org.opengis.annotation.Specification.*; /** * A 1-dimensional coordinate system containing a single time axis. * This coordinate system is used to describe the temporal position of a point - * in the specified time units from a specified time origin. + * in the specified time units from a time origin implied by the temporal datum. * *

This type of CS can be used by coordinate reference systems of type * {@link org.opengis.referencing.crs.TemporalCRS}.

* - * @author Martin Desruisseaux (IRD) - * @version 3.0 + * @author Martin Desruisseaux (IRD, Geomatys) + * @version 3.1 * @since 2.0 * * @see CSAuthorityFactory#createTimeCS(String) * @see CSFactory#createTimeCS(Map, CoordinateSystemAxis) + * + * @departure integration + * ISO 19111:2019 renamed this interface from {@code TimeCS} to {@code TemporalCS}. + * GeoAPI has kept the ISO 19111:2007 interface name for historical reasons, + * but also to emphasize the relationship with the {@link java.time} package. */ -@UML(identifier="CS_TimeCS", specification=ISO_19111, version=2007) +@UML(identifier="TemporalCS", specification=ISO_19111) public interface TimeCS extends CoordinateSystem { + /** + * Returns the unit of measurement of coordinate values. The returned unit is equivalent to the unit + * returned by {@link CoordinateSystemAxis#getUnit()}, but expressed as a {@link java.time} object, + * preferably an instance from the {@link ChronoUnit} enumeration. + * + *

Note that contrarily to the usual units of measurement, the duration of {@link java.time} units can vary. + * For example {@link ChronoUnit#DAYS} is estimated to be about 24 hours long, because the actual + * duration can vary due to daylight saving time changes. Implementations can specify whether the temporal + * unit is estimated or exact with {@link TemporalUnit#isDurationEstimated()}.

+ * + *

Default implementation

+ * The default implementation returns a {@link ChronoUnit} or an integer multiple of a {@code ChronoUnit} + * with a duration approximately equals to the duration of the coordinate system axis unit. + * "Approximately equals" is defined as a tolerance of twelve hours for {@code ChronoUnit} + * of one month or longer (in which case the duration is flagged as estimated), + * or one ULP otherwise. + * + * @return unit measurement of coordinate values, preferably as a {@link ChronoUnit} enumeration value. + * + * @see ChronoUnit#SECONDS + * @see ChronoUnit#DAYS + * @see ChronoUnit#YEARS + * + * @since 3.1 + */ + default TemporalUnit getUnit() { + return TimeUnit.valueOf(getAxis(0).getUnit().asType(Time.class)); + } } diff --git a/geoapi/src/main/java/org/opengis/referencing/cs/TimeUnit.java b/geoapi/src/main/java/org/opengis/referencing/cs/TimeUnit.java new file mode 100644 index 000000000..343f00876 --- /dev/null +++ b/geoapi/src/main/java/org/opengis/referencing/cs/TimeUnit.java @@ -0,0 +1,277 @@ +/* + * GeoAPI - Java interfaces for OGC/ISO standards + * Copyright © 2024 Open Geospatial Consortium, Inc. + * http://www.geoapi.org + * + * Licensed 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.opengis.referencing.cs; + +import java.util.Map; +import java.util.TreeMap; +import java.util.Arrays; +import java.io.Serializable; +import java.time.Duration; +import java.time.temporal.ChronoUnit; +import java.time.temporal.Temporal; +import java.time.temporal.TemporalUnit; +import javax.measure.Unit; +import javax.measure.quantity.Time; +import javax.measure.UnconvertibleException; + + +/** + * Mapping from {@link javax.measure} API to {@link java.time} API. + * This implementation delegates practically all work to {@link ChronoUnit}. + * The code in this class is mostly about choosing which {@link ChronoUnit} + * seems the best match for a given unit of measurement. + * + * @author Martin Desruisseaux (Geomatys) + * @version 3.1 + * @since 3.1 + */ +final class TimeUnit implements TemporalUnit, Serializable { + /** + * For cross-version compatibility. + */ + private static final long serialVersionUID = -6300465049394758570L; + + /** + * The duration of all supported temporal units, in seconds. + * Elements in this array must be sorted in increasing order. + */ + private static final double[] DURATIONS; + + /** + * The temporal units corresponding to each element in the {@link #DURATIONS} array. + */ + private static final ChronoUnit[] UNITS; + + /** + * Index of the unit for which an estimated duration may be used. {@link ChronoUnit} API + * considers all durations equal or greater than one day as estimated rather than exact. + * Therefor, it is not a violation of {@link java.time} API if the tolerance threshold + * is relaxed for those units. So this class tolerates a half-day difference for units + * equal or greater than one month. + */ + private static final int RELAX_INDEX; + + /** + * Initialize the static fields. + */ + static { + final var m = new TreeMap(); + for (final ChronoUnit unit : ChronoUnit.values()) { + if (unit != ChronoUnit.FOREVER) { + final Duration duration = unit.getDuration(); + m.put(duration.getSeconds() + duration.getNano() / 1E+9, unit); + } + } + DURATIONS = new double[m.size()]; + UNITS = new ChronoUnit[DURATIONS.length]; + int i = 0, month = 0; + for (final Map.Entry e : m.entrySet()) { + if ((UNITS[i] = e.getValue()) == ChronoUnit.MONTHS) month = i; + DURATIONS[i++] = e.getKey(); + } + RELAX_INDEX = month; + } + + /** + * The duration of this {@code TimeUnit}, as an amount of a {@code ChronoUnit}. + * Shall be a number greater than 1. + */ + private final long duration; + + /** + * The unit of the duration. + */ + private final ChronoUnit unit; + + /** + * Creates a new temporal unit as an integer amount of a standard {@code ChronoUnit}. + * + * @param duration duration in amount of {@code unit}. + * @param unit unit of the {@code duration} argument. + */ + private TimeUnit(final long duration, final ChronoUnit unit) { + this.duration = duration; + this.unit = unit; + } + + /** + * Searches for a temporal unit equivalent to the given unit of measurement. + * If the duration of the given unit is equal to the duration of one of the {@link ChronoUnit}s, + * then that unit is returned. Otherwise, if the duration can be expressed as a multiple of one + * of the {@link ChronoUnit}s, then the multiple and the unit are wrapped in a {@code TimeUnit}. + * + * @param unit the unit of measurement to map. + * @return the temporal unit equivalent to the given unit of measurement. + * @throws ArithmeticException if the given unit overflows or underflows the capability of the {@link java.time} API. + */ + static TemporalUnit valueOf(final Unit