001/*
002 *    GeoAPI - Java interfaces for OGC/ISO standards
003 *    http://www.geoapi.org
004 *
005 *    Copyright (C) 2011-2019 Open Geospatial Consortium, Inc.
006 *    All Rights Reserved. http://www.opengeospatial.org/ogc/legal
007 *
008 *    Permission to use, copy, and modify this software and its documentation, with
009 *    or without modification, for any purpose and without fee or royalty is hereby
010 *    granted, provided that you include the following on ALL copies of the software
011 *    and documentation or portions thereof, including modifications, that you make:
012 *
013 *    1. The full text of this NOTICE in a location viewable to users of the
014 *       redistributed or derivative work.
015 *    2. Notice of any changes or modifications to the OGC files, including the
016 *       date changes were made.
017 *
018 *    THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE
019 *    NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
020 *    TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT
021 *    THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY
022 *    PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
023 *
024 *    COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR
025 *    CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION.
026 *
027 *    The name and trademarks of copyright holders may NOT be used in advertising or
028 *    publicity pertaining to the software without specific, written prior permission.
029 *    Title to copyright in this software and any associated documentation will at all
030 *    times remain with copyright holders.
031 */
032package org.opengis.test;
033
034import org.opengis.geometry.DirectPosition;
035import org.opengis.referencing.crs.GeographicCRS;
036import org.opengis.referencing.crs.ProjectedCRS;
037import org.opengis.referencing.operation.MathTransform;
038
039
040/**
041 * Modifies the tolerance threshold before to compare a calculated value against its expected value.
042 * When a {@link TestCase} is run, GeoAPI performs the following steps:
043 *
044 * <ul>
045 *   <li>Scan every {@link ImplementationDetails} on the classpath and invoke their
046 *       {@link ImplementationDetails#tolerance(MathTransform) tolerance(…)}
047 *       method for the {@link MathTransform} being tested.</li>
048 *
049 *   <li>For each non-null {@code ToleranceModifier}, invoke the {@link #adjust(double[],
050 *       DirectPosition, CalculationType) adjust(…)} method. The first given argument will be
051 *       the default tolerance thresholds computed by the {@link TestCase} being run. Implementation
052 *       can modify those tolerances in an arbitrary number of dimensions.</li>
053 * </ul>
054 *
055 * Different implementations are available for different cases. For example:
056 *
057 * <ul>
058 *   <li>Allowing a greater tolerance threshold along the vertical axis compared to the
059 *       horizontal axis.</li>
060 *   <li>In a geographic CRS, ignoring offsets of 360° in longitude.</li>
061 *   <li>In a geographic CRS, ignoring the longitude value if the latitude is at a pole.</li>
062 * </ul>
063 *
064 * @author  Martin Desruisseaux (Geomatys)
065 * @version 3.1
066 * @since   3.1
067 */
068public interface ToleranceModifier {
069    /**
070     * Converts λ and φ tolerance values from metres to degrees before comparing
071     * geographic coordinates. The tolerance for the longitude (λ) and latitude (φ)
072     * ordinate values are converted from metres to degrees using the standard length of one
073     * nautical mile ({@value org.opengis.test.ToleranceModifiers#NAUTICAL_MILE} metres per
074     * minute of angle). Next, the λ tolerance is adjusted according the distance of
075     * the φ ordinate value to the pole. In the extreme case where the coordinate to compare
076     * is located at a pole, then the tolerance is 360° in longitude values.
077     *
078     * <p>This modifier assumes that geographic coordinates are expressed in decimal degrees in
079     * (<var>longitude</var>, <var>latitude</var>) order, as documented in the {@linkplain
080     * org.opengis.referencing.operation.MathTransformFactory#createParameterizedTransform
081     * parameterized transform contructor}.</p>
082     *
083     * @see ToleranceModifiers#geographic(int, int)
084     */
085    ToleranceModifier GEOGRAPHIC = new ToleranceModifiers.Geographic(0, 1);
086
087    /**
088     * Converts φ and λ tolerance values from metres to degrees before comparing
089     * geographic coordinates. This modifier is identical to the {@link #GEOGRAPHIC} tolerance
090     * modifier, except that φ and λ axes are interchanged. This is the most common
091     * modifier used when testing {@link GeographicCRS} instances created from the
092     * <a href="http://www.epsg.org">EPSG</a> database.
093     *
094     * @see ToleranceModifiers#geographic(int, int)
095     */
096    ToleranceModifier GEOGRAPHIC_φλ = new ToleranceModifiers.Geographic(1, 0);
097
098    /**
099     * Converts λ and φ tolerance values from metres to degrees before comparing
100     * the result of an <cite>inverse projection</cite>. For <cite>forward projections</cite>
101     * and all other calculations, the tolerance values are left unchanged.
102     *
103     * <p>The modifier performs the work documented in {@link #GEOGRAPHIC} if and only if the
104     * {@link CalculationType} is {@link CalculationType#INVERSE_TRANSFORM INVERSE_TRANSFORM}.
105     * For all other cases, the modifier does nothing.</p>
106     *
107     * @see ToleranceModifiers#projection(int, int)
108     */
109    ToleranceModifier PROJECTION = new ToleranceModifiers.Projection(0, 1);
110
111    /**
112     * Converts φ and λ tolerance values from metres to degrees before comparing
113     * the result of an <cite>inverse projection</cite>. This modifier is identical to the
114     * {@link #PROJECTION} tolerance modifier, except that φ and λ axes are
115     * interchanged. This is the most common modifier used when testing {@link ProjectedCRS}
116     * instances created from the <a href="http://www.epsg.org">EPSG</a> database.
117     *
118     * @see ToleranceModifiers#projection(int, int)
119     */
120    ToleranceModifier PROJECTION_FROM_φλ = new ToleranceModifiers.Projection(1, 0);
121
122    /**
123     * Makes the tolerance values relative to the ordinate values being compared. For each
124     * dimension, this modifier multiplies the tolerance threshold by the ordinate value and
125     * ensure that the result is not lower than the original threshold (in order to allow
126     * comparisons of values close to zero):
127     *
128     * <blockquote><var>tolerance</var>[i] = max(<var>tolerance</var>[i],
129     * <var>tolerance</var>[i] × <var>ordinate</var>[i])</blockquote>
130     */
131    ToleranceModifier RELATIVE = new ToleranceModifiers.Relative();
132
133    /**
134     * Adjusts the tolerance threshold for comparing the given coordinate along each dimensions.
135     *
136     * @param  tolerance   the default tolerance threshold determined by the {@link TestCase}
137     *                     being run. This array can be modified in-place.
138     * @param  coordinate  the coordinate being compared, in the <em>target</em> CRS.
139     * @param  mode        Indicates if the coordinate being compared is the result of a direct
140     *                     or inverse transform, or if strict equality is requested.
141     */
142    void adjust(double[] tolerance, DirectPosition coordinate, CalculationType mode);
143}