001/*
002 *    GeoAPI - Java interfaces for OGC/ISO standards
003 *    Copyright © 2011-2024 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.test;
019
020import org.opengis.geometry.DirectPosition;
021import org.opengis.referencing.crs.GeographicCRS;
022import org.opengis.referencing.crs.ProjectedCRS;
023
024
025/**
026 * Modifies the tolerance threshold before to compare a calculated value against its expected value.
027 * When a {@link TestCase} is run, GeoAPI invoke the {@link #adjust(double[], DirectPosition, CalculationType)
028 * adjust(…)} method. The first given argument will be the default tolerance thresholds computed by the
029 * {@link TestCase} being run. Implementation can modify those tolerances in an arbitrary number of dimensions.
030 * Different implementations are available for different cases. For example:
031 *
032 * <ul>
033 *   <li>Allowing a greater tolerance threshold along the vertical axis compared to the
034 *       horizontal axis.</li>
035 *   <li>In a geographic CRS, ignoring offsets of 360° in longitude.</li>
036 *   <li>In a geographic CRS, ignoring the longitude value if the latitude is at a pole.</li>
037 * </ul>
038 *
039 * @author  Martin Desruisseaux (Geomatys)
040 * @version 3.1
041 * @since   3.1
042 */
043public interface ToleranceModifier {
044    /**
045     * Converts λ and φ tolerance values from metres to degrees before comparing
046     * geographic coordinates. The tolerance for the longitude (λ) and latitude (φ)
047     * coordinate values are converted from metres to degrees using the standard length of one
048     * nautical mile ({@value org.opengis.test.ToleranceModifiers#NAUTICAL_MILE} metres per
049     * minute of angle). Next, the λ tolerance is adjusted according the distance of
050     * the φ coordinate value to the pole. In the extreme case where the coordinate to compare
051     * is located at a pole, then the tolerance is 360° in longitude values.
052     *
053     * <p>This modifier assumes that geographic coordinates are expressed in decimal degrees in
054     * (<var>longitude</var>, <var>latitude</var>) order, as documented in the {@linkplain
055     * org.opengis.referencing.operation.MathTransformFactory#createParameterizedTransform
056     * parameterized transform contructor}.</p>
057     *
058     * @see ToleranceModifiers#geographic(int, int)
059     */
060    ToleranceModifier GEOGRAPHIC = new ToleranceModifiers.Geographic(0, 1);
061
062    /**
063     * Converts φ and λ tolerance values from metres to degrees before comparing
064     * geographic coordinates. This modifier is identical to the {@link #GEOGRAPHIC} tolerance
065     * modifier, except that φ and λ axes are interchanged. This is the most common
066     * modifier used when testing {@link GeographicCRS} instances created from the
067     * <a href="https://epsg.org">EPSG geodetic registry</a>.
068     *
069     * @see ToleranceModifiers#geographic(int, int)
070     */
071    ToleranceModifier GEOGRAPHIC_φλ = new ToleranceModifiers.Geographic(1, 0);
072
073    /**
074     * Converts λ and φ tolerance values from metres to degrees before comparing
075     * the result of an <i>reverse projection</i>. For <i>forward projections</i>
076     * and all other calculations, the tolerance values are left unchanged.
077     *
078     * <p>The modifier performs the work documented in {@link #GEOGRAPHIC} if and only if the
079     * {@link CalculationType} is {@link CalculationType#INVERSE_TRANSFORM INVERSE_TRANSFORM}.
080     * For all other cases, the modifier does nothing.</p>
081     *
082     * @see ToleranceModifiers#projection(int, int)
083     */
084    ToleranceModifier PROJECTION = new ToleranceModifiers.Projection(0, 1);
085
086    /**
087     * Converts φ and λ tolerance values from metres to degrees before comparing
088     * the result of an <i>reverse projection</i>. This modifier is identical to the
089     * {@link #PROJECTION} tolerance modifier, except that φ and λ axes are
090     * interchanged. This is the most common modifier used when testing {@link ProjectedCRS}
091     * instances created from the <a href="https://epsg.org">EPSG geodetic registry</a>.
092     *
093     * @see ToleranceModifiers#projection(int, int)
094     */
095    ToleranceModifier PROJECTION_FROM_φλ = new ToleranceModifiers.Projection(1, 0);
096
097    /**
098     * Makes the tolerance values relative to the coordinate values being compared. For each
099     * dimension, this modifier multiplies the tolerance threshold by the coordinate value and
100     * ensure that the result is not lower than the original threshold (in order to allow
101     * comparisons of values close to zero):
102     *
103     * <blockquote><var>tolerance</var>[i] = max(<var>tolerance</var>[i],
104     * <var>tolerance</var>[i] × <var>coordinate</var>[i])</blockquote>
105     */
106    ToleranceModifier RELATIVE = new ToleranceModifiers.Relative();
107
108    /**
109     * Adjusts the tolerance threshold for comparing the given coordinate along each dimensions.
110     *
111     * @param  tolerances   the default tolerance thresholds determined by the {@link TestCase} being run.
112     *                      This array can be modified in-place.
113     * @param  coordinates  the coordinates being compared, in the <em>target</em> CRS.
114     * @param  mode         indicates if the coordinate being compared is the result of a direct
115     *                      or inverse transform, or if strict equality is requested.
116     */
117    void adjust(double[] tolerances, DirectPosition coordinates, CalculationType mode);
118}