001/*
002 *    GeoAPI - Java interfaces for OGC/ISO standards
003 *    Copyright © 2003-2023 Open Geospatial Consortium, Inc.
004 *    http://www.geoapi.org
005 *
006 *    Licensed under the Apache License, Version 2.0 (the "License");
007 *    you may not use this file except in compliance with the License.
008 *    You may obtain a copy of the License at
009 *
010 *        http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *    Unless required by applicable law or agreed to in writing, software
013 *    distributed under the License is distributed on an "AS IS" BASIS,
014 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 *    See the License for the specific language governing permissions and
016 *    limitations under the License.
017 */
018package org.opengis.referencing.crs;
019
020import java.util.Map;
021import org.opengis.referencing.datum.Datum;
022import org.opengis.referencing.datum.DatumEnsemble;
023import org.opengis.referencing.cs.CoordinateSystem;
024import org.opengis.referencing.operation.Conversion;
025import org.opengis.annotation.UML;
026
027import static org.opengis.annotation.Obligation.MANDATORY;
028import static org.opengis.annotation.Specification.*;
029
030
031/**
032 * A <abbr>CRS</abbr> that is defined by applying a coordinate conversion to another preexisting <abbr>CRS</abbr>.
033 * The derived <abbr>CRS</abbr> inherits its datum (reference frame) or datum ensemble from its base <abbr>CRS</abbr>.
034 * A {@code DerivedCRS} instance may also implement one of the interfaces listed below,
035 * provided that the conditions in the right column are met:
036 *
037 * <table class="ogc">
038 *   <caption>Derived <abbr>CRS</abbr> types</caption>
039 *   <tr><th>Type</th>                   <th>Conditions</th></tr>
040 *   <tr><td>{@link ProjectedCRS}</td>   <td>Base CRS is a {@link GeographicCRS} and conversion is a map projection.</td></tr>
041 *   <tr><td>{@link GeodeticCRS}</td>    <td>Base CRS is also a {@code GeodeticCRS}.</td></tr>
042 *   <tr><td>{@link VerticalCRS}</td>    <td>Base CRS is also a {@code VerticalCRS}.</td></tr>
043 *   <tr><td>{@link TemporalCRS}</td>    <td>Base CRS is also a {@code TemporalCRS}.</td></tr>
044 *   <tr><td>{@link EngineeringCRS}</td> <td>Base CRS is a {@code GeodeticCRS}, {@code ProjectedCRS} or {@code EngineeringCRS}.</td></tr>
045 * </table>
046 *
047 * <h2>Projected <abbr>CRS</abbr></h2>
048 * In the special case where the <abbr>CRS</abbr> is derived from a base {@link GeographicCRS} by applying
049 * a coordinate conversion known as a map projection to latitude and longitude ellipsoidal coordinate values,
050 * the {@link ProjectedCRS} subtype should be used. Projected <abbr>CRS</abbr>s are modeled as a special case
051 * of derived <abbr>CRS</abbr> because of their importance in geographic information.
052 *
053 * <h2>Derived projected <abbr>CRS</abbr></h2>
054 * In the special case where the <abbr>CRS</abbr> is derived from a base {@link ProjectedCRS},
055 * the coordinate system of the derived <abbr>CRS</abbr> is not necessarily Cartesian.
056 * But the derived <abbr>CRS</abbr> still inherit the distortion characteristics of the base projected <abbr>CRS</abbr>.
057 *
058 * @author  OGC Topic 2 (for abstract model and documentation)
059 * @author  Martin Desruisseaux (IRD, Geomatys)
060 * @version 3.1
061 * @since   1.0
062 *
063 * @see CRSAuthorityFactory#createDerivedCRS(String)
064 * @see CRSFactory#createDerivedCRS(Map, CoordinateReferenceSystem, Conversion, CoordinateSystem)
065 */
066@SuppressWarnings("deprecation")
067@UML(identifier="DerivedCRS", specification=ISO_19111)
068public interface DerivedCRS extends GeneralDerivedCRS {
069    /**
070     * Returns the <abbr>CRS</abbr> that is the base for this derived <abbr>CRS</abbr>.
071     * This is the {@linkplain Conversion#getSourceCRS() source <abbr>CRS</abbr>}
072     * of the {@linkplain #getConversionFromBase() deriving conversion}.
073     *
074     * <div class="warning"><b>Upcoming API change — specialization</b><br>
075     * According ISO 19111, the return type should be {@link SingleCRS}.
076     * This change may be applied in GeoAPI 4.0.
077     * </div>
078     *
079     * @return the <abbr>CRS</abbr> that is the base for this derived <abbr>CRS</abbr>.
080     */
081    @Override
082    @UML(identifier="baseCRS", obligation=MANDATORY, specification=ISO_19111)
083    CoordinateReferenceSystem getBaseCRS();
084
085    /**
086     * Returns the conversion from the base <abbr>CRS</abbr> to this derived <abbr>CRS</abbr>.
087     * The source <abbr>CRS</abbr> of the conversion, if non null, shall be the {@linkplain #getBaseCRS() base <abbr>CRS</abbr>}.
088     * The target <abbr>CRS</abbr> of the conversion, if non-null, shall be this <abbr>CRS</abbr>.
089     *
090     * @return the conversion from the base <abbr>CRS</abbr> to this derived <abbr>CRS</abbr>.
091     *
092     * @departure rename
093     *   Was {@code toBase} in OGC 01-009, {@code conversion} in ISO 19111:2007
094     *   and {@code derivingConversion} in ISO 19111:2019. By analogy with 01-009,
095     *   GeoAPI defines a method name which contains the "{@code FromBase}" words
096     *   for making clear which <abbr>CRS</abbr> is the source or which one is the target.
097     */
098    @Override
099    @UML(identifier="derivingConversion", obligation=MANDATORY, specification=ISO_19111)
100    Conversion getConversionFromBase();
101
102    /**
103     * Returns the same datum as the base <abbr>CRS</abbr>.
104     * This property may be null if the base <abbr>CRS</abbr> is related to an object
105     * identified only by a {@linkplain #getDatumEnsemble() datum ensemble}.
106     *
107     * @return the datum of the base <abbr>CRS</abbr>, or {@code null} if the base is related to
108     *         an object identified only by a {@linkplain #getDatumEnsemble() datum ensemble}.
109     */
110    @Override
111    default Datum getDatum() {
112        final CoordinateReferenceSystem crs = getBaseCRS();
113        return (crs instanceof SingleCRS) ? ((SingleCRS) getBaseCRS()).getDatum() : null;
114    }
115
116    /**
117     * Returns the same datum ensemble as the base <abbr>CRS</abbr>.
118     * This property may be null if the base <abbr>CRS</abbr> is related to an object
119     * identified only by a single {@linkplain #getDatum() datum}.
120     *
121     * @return the datum ensemble of the base <abbr>CRS</abbr>, or {@code null} if the base is
122     *         related to an object identified only by a single {@linkplain #getDatum() datum}.
123     *
124     * @since 3.1
125     */
126    @Override
127    default DatumEnsemble<?> getDatumEnsemble() {
128        final CoordinateReferenceSystem crs = getBaseCRS();
129        return (crs instanceof SingleCRS) ? ((SingleCRS) getBaseCRS()).getDatumEnsemble() : null;
130    }
131}