001    /*
002     *    GeoAPI - Java interfaces for OGC/ISO standards
003     *    http://www.geoapi.org
004     *
005     *    Copyright (C) 2004-2012 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     */
032    package org.opengis.geometry;
033    
034    import java.awt.geom.Rectangle2D; // Used in @see javadoc tags
035    
036    import org.opengis.referencing.cs.RangeMeaning; // For javadoc
037    import org.opengis.referencing.crs.CoordinateReferenceSystem;
038    import org.opengis.annotation.UML;
039    
040    import static org.opengis.annotation.Obligation.*;
041    import static org.opengis.annotation.Specification.*;
042    
043    
044    /**
045     * A minimum bounding box or rectangle. Regardless of dimension, an {@code Envelope} can
046     * be represented without ambiguity as two direct positions (coordinate points). To encode an
047     * {@code Envelope}, it is sufficient to encode these two points. This is consistent with
048     * all of the data types in this specification, their state is represented by their publicly
049     * accessible attributes.
050     *
051     * <blockquote><font size="-1"><b>Spanning the anti-meridian of a geographic CRS</b><br>
052     * The <cite>Web Coverage Service</cite> (WCS) 1.1 specification uses an extended interpretation
053     * of the bounding box definition. In a WCS 1.1 data structure, the {@linkplain #getUpperCorner()
054     * upper corner} defines the edges region in the directions of <em>increasing</em> coordinate
055     * values in the envelope CRS, while the {@linkplain #getLowerCorner() lower corner} defines the
056     * edges region in the direction of <em>decreasing</em> coordinate values. They are usually the
057     * algebraic maximum and minimum coordinates respectively, but not always. For example, an envelope
058     * crossing the anti-meridian could have an upper corner longitude less than the lower corner
059     * longitude.
060     * <p>
061     * Whatever an envelope supports the extended bounding box interpretation or not is
062     * implementation-dependent. If supported, the extended interpretation is applicable only to
063     * axes having a {@link RangeMeaning#WRAPAROUND WRAPAROUND} range meaning - usually the
064     * longitude axis.</font></blockquote>
065     *
066     * @departure easeOfUse
067     *   The ISO specification defines this interface in the <code>coordinate</code> sub-package.
068     *   GeoAPI moved this interface into the <code>org.opengis.geometry</code> root package for
069     *   convenience, because it is extensively used.
070     *
071     * @author  Martin Desruisseaux (IRD)
072     * @version 3.0
073     * @since   1.0
074     *
075     * @see org.opengis.coverage.grid.GridEnvelope
076     *
077     * @navassoc 1 - - CoordinateReferenceSystem
078     * @navassoc 2 - - DirectPosition
079     */
080    @UML(identifier="GM_Envelope", specification=ISO_19107)
081    public interface Envelope {
082        /**
083         * Returns the envelope coordinate reference system, or {@code null} if unknown.
084         * If non-null, it shall be the same as {@linkplain #getLowerCorner lower corner}
085         * and {@linkplain #getUpperCorner upper corner} CRS.
086         *
087         * @return The envelope CRS, or {@code null} if unknown.
088         *
089         * @departure easeOfUse
090         *   ISO does not define this method - the CRS or the dimension can be obtained only through
091         *   one of the corner <code>DirectPosition</code> objects. GeoAPI adds this method for
092         *   convenience as a more direct way of obtaining the information and to free the user from
093         *   the need to choose an arbitrary corner (very defensive code might feel the need to get
094         *   the value from both corners to check they were the same).
095         *
096         * @since 2.1
097         */
098        CoordinateReferenceSystem getCoordinateReferenceSystem();
099    
100        /**
101         * The length of coordinate sequence (the number of entries) in this envelope. Mandatory
102         * even when the {@linkplain #getCoordinateReferenceSystem coordinate reference system}
103         * is unknown.
104         *
105         * @return The dimensionality of this envelope.
106         *
107         * @departure easeOfUse
108         *   ISO does not define this method - the CRS or the dimension can be obtained only through
109         *   one of the corner <code>DirectPosition</code> objects. GeoAPI adds this method for
110         *   convenience as a more direct way of obtaining the information and to free the user from
111         *   the need to choose an arbitrary corner (very defensive code might feel the need to get
112         *   the value from both corners to check they were the same).
113         *
114         * @since 2.0
115         */
116        int getDimension();
117    
118        /**
119         * The limits in the direction of decreasing ordinate values for each dimension. This
120         * is typically a coordinate position consisting of all the minimal ordinates for each
121         * dimension for all points within the {@code Envelope}.
122         *
123         * <blockquote><font size="-1"><b>Spanning the anti-meridian of a geographic CRS</b><br>
124         * The <cite>Web Coverage Service</cite> (WCS) 1.1 specification uses an extended interpretation
125         * of the bounding box definition. In a WCS 1.1 data structure, the lower corner defines the
126         * edges region in the directions of <em>decreasing</em> coordinate values in the envelope CRS.
127         * This is usually the algebraic {@linkplain #getMinimum(int) minimum} coordinates, but not
128         * always. For example, an envelope crossing the anti-meridian could have a lower corner
129         * longitude greater than the {@linkplain #getUpperCorner() upper corner} longitude.
130         * <p>
131         * Whatever this envelope supports the extended bounding box interpretation or not is
132         * implementation-dependent. If supported, the extended interpretation is applicable only to
133         * axes having a {@link RangeMeaning#WRAPAROUND WRAPAROUND} range meaning - usually the
134         * longitude axis. On typical map representations, the <code>getLowerCorner()</code> method
135         * name still "visually" appropriate since the <cite>lower</cite> corner still toward the
136         * bottom of the map even if the left corner became the right corner.</font></blockquote>
137         *
138         * @return The lower corner, typically (but not necessarily) containing minimal ordinate values.
139         */
140        @UML(identifier="lowerCorner", obligation=MANDATORY, specification=ISO_19107)
141        DirectPosition getLowerCorner();
142    
143        /**
144         * The limit in the direction of increasing ordinate values for each dimension. This
145         * is typically a coordinate position consisting of all the maximal ordinates for each
146         * dimension for all points within the {@code Envelope}.
147         *
148         * <blockquote><font size="-1"><b>Spanning the anti-meridian of a geographic CRS</b><br>
149         * The <cite>Web Coverage Service</cite> (WCS) 1.1 specification uses an extended interpretation
150         * of the bounding box definition. In a WCS 1.1 data structure, the upper corner defines the
151         * edges region in the directions of <em>increasing</em> coordinate values in the envelope CRS.
152         * This is usually the algebraic {@linkplain #getMaximum(int) maximum} coordinates, but not
153         * always. For example, an envelope crossing the anti-meridian could have an upper corner
154         * longitude less than the {@linkplain #getLowerCorner() lower corner} longitude.
155         * <p>
156         * Whatever this envelope supports the extended bounding box interpretation or not is
157         * implementation-dependent. If supported, the extended interpretation is applicable only to
158         * axes having a {@link RangeMeaning#WRAPAROUND WRAPAROUND} range meaning - usually the
159         * longitude axis. On typical map representations, the <code>getUpperCorner()</code> method
160         * name still "visually" appropriate since the <cite>upper</cite> corner still toward the
161         * top of the map even if the right corner became the left corner.</font></blockquote>
162         *
163         * @return The upper corner, typically (but not necessarily) containing maximal ordinate values.
164         */
165        @UML(identifier="upperCorner", obligation=MANDATORY, specification=ISO_19107)
166        DirectPosition getUpperCorner();
167    
168        /**
169         * Returns the minimal ordinate value for the specified dimension. In the typical case of
170         * envelopes <em>not</em> spanning the anti-meridian, this method is a shortcut for the
171         * following code without the cost of creating a temporary {@link DirectPosition} object:
172         *
173         * <blockquote><code>
174         * minimum = {@linkplain #getLowerCorner}.{@linkplain DirectPosition#getOrdinate getOrdinate}(dimension);
175         * </code></blockquote>
176         *
177         * <blockquote><font size="-1"><b>Spanning the anti-meridian of a geographic CRS</b><br>
178         * If the axis range meaning is {@link RangeMeaning#WRAPAROUND WRAPAROUND} and this envelope
179         * supports the {@linkplain #getLowerCorner() lower} and {@linkplain #getUpperCorner() upper}
180         * corners extended interpretation, then <var>lower</var> may possibly be greater than
181         * <var>upper</var>. In such case, implementations shall select some value such that
182         * <var>minimum</var> &lt; <var>maximum</var> (ignoring NaN). It may be the
183         * {@linkplain org.opengis.referencing.cs.CoordinateSystemAxis#getMinimumValue() axis minimum value},
184         * {@linkplain Double#NEGATIVE_INFINITY negative infinity}, {@linkplain Double#NaN NaN} or other
185         * value, at implementor choice.</font></blockquote>
186         *
187         * @param  dimension The dimension for which to obtain the ordinate value.
188         * @return The minimal ordinate at the given dimension.
189         * @throws IndexOutOfBoundsException If the given index is negative or is equals or greater
190         *         than the {@linkplain #getDimension() envelope dimension}.
191         *
192         * @departure easeOfUse
193         *   This method is not part of ISO specification. GeoAPI adds this method for convenience and
194         *   efficiency, since some implementations might store the minimum and maximum ordinate values
195         *   directly in the <code>Envelope</code> itself rather than in a contained
196         *   <code>DirectPosition</code> corner.
197         *
198         * @see Rectangle2D#getMinX()
199         * @see Rectangle2D#getMinY()
200         *
201         * @since 2.0
202         */
203        double getMinimum(int dimension) throws IndexOutOfBoundsException;
204    
205        /**
206         * Returns the maximal ordinate value for the specified dimension. In the typical case of
207         * envelopes <em>not</em> spanning the anti-meridian, this method is a shortcut for the
208         * following code without the cost of creating a temporary {@link DirectPosition} object:
209         *
210         * <blockquote><code>
211         * maximum = {@linkplain #getUpperCorner}.{@linkplain DirectPosition#getOrdinate getOrdinate}(dimension);
212         * </code></blockquote>
213         *
214         * <blockquote><font size="-1"><b>Spanning the anti-meridian of a geographic CRS</b><br>
215         * If the axis range meaning is {@link RangeMeaning#WRAPAROUND WRAPAROUND} and this envelope
216         * supports the {@linkplain #getLowerCorner() lower} and {@linkplain #getUpperCorner() upper}
217         * corners extended interpretation, then <var>upper</var> may possibly be less than
218         * <var>lower</var>. In such case, implementations shall select some value such that
219         * <var>maximum</var> &gt; <var>minimum</var> (ignoring NaN). It may be the
220         * {@linkplain org.opengis.referencing.cs.CoordinateSystemAxis#getMaximumValue() axis maximum value},
221         * {@linkplain Double#POSITIVE_INFINITY positive infinity}, {@linkplain Double#NaN NaN} or other
222         * value, at implementor choice.</font></blockquote>
223         *
224         * @param  dimension The dimension for which to obtain the ordinate value.
225         * @return The maximal ordinate at the given dimension.
226         * @throws IndexOutOfBoundsException If the given index is negative or is equals or greater
227         *         than the {@linkplain #getDimension() envelope dimension}.
228         *
229         * @departure easeOfUse
230         *   This method is not part of ISO specification. GeoAPI adds this method for convenience and
231         *   efficiency, since some implementations might store the minimum and maximum ordinate values
232         *   directly in the <code>Envelope</code> itself rather than in a contained
233         *   <code>DirectPosition</code> corner.
234         *
235         * @see Rectangle2D#getMaxX()
236         * @see Rectangle2D#getMaxY()
237         *
238         * @since 2.0
239         */
240        double getMaximum(int dimension) throws IndexOutOfBoundsException;
241    
242        /**
243         * Returns the median ordinate along the specified dimension. In most cases, the result is
244         * equals (minus rounding error) to:
245         *
246         * <blockquote><code>
247         * median = ({@linkplain #getMinimum getMinimum}(dimension) + {@linkplain #getMaximum getMaximum}(dimension)) / 2;
248         * </code></blockquote>
249         *
250         * <blockquote><font size="-1"><b>Spanning the anti-meridian of a geographic CRS</b><br>
251         * If this envelope supports the {@linkplain #getLowerCorner() lower} and
252         * {@linkplain #getUpperCorner() upper} corners extended interpretation, and if the axis
253         * range meaning is {@link RangeMeaning#WRAPAROUND WRAPAROUND}, then a special cases occurs
254         * when <var>upper</var> &lt; <var>lower</var>. In such cases, the ordinate values from the
255         * lower and upper corner may be used instead than the minimum and maximum values, with the
256         * periodicity (360° for longitudes) added to the upper value before to perform the median
257         * calculation.
258         * <p>
259         * Implementations are free to use variants of the above algorithm. For example some
260         * libraries may add different multiples of the periodicity in order to ensure that the
261         * median value is inside the axis range.</font></blockquote>
262         *
263         * @param  dimension The dimension for which to obtain the ordinate value.
264         * @return The median ordinate at the given dimension.
265         * @throws IndexOutOfBoundsException If the given index is negative or is equals or greater
266         *         than the {@linkplain #getDimension() envelope dimension}.
267         *
268         * @departure easeOfUse
269         *   This method is not part of ISO specification. GeoAPI adds this method for convenience and
270         *   efficiency, since some implementations might store the minimum and maximum ordinate values
271         *   directly in the <code>Envelope</code> itself rather than in a contained
272         *   <code>DirectPosition</code> corner.
273         *
274         * @see Rectangle2D#getCenterX()
275         * @see Rectangle2D#getCenterY()
276         *
277         * @since 2.2
278         */
279        double getMedian(int dimension) throws IndexOutOfBoundsException;
280    
281        /**
282         * Returns the envelope span (typically width or height) along the specified dimension.
283         * In most cases, the result is equals (minus rounding error) to:
284         *
285         * <blockquote><code>
286         * span = {@linkplain #getMaximum getMaximum}(dimension) - {@linkplain #getMinimum getMinimum}(dimension);
287         * </code></blockquote>
288         *
289         * <blockquote><font size="-1"><b>Spanning the anti-meridian of a geographic CRS</b><br>
290         * If this envelope supports the {@linkplain #getLowerCorner() lower} and
291         * {@linkplain #getUpperCorner() upper} corners extended interpretation, and if the axis
292         * range meaning is {@link RangeMeaning#WRAPAROUND WRAPAROUND}, then a special cases occurs
293         * when <var>upper</var> &lt; <var>lower</var>. In such cases, the ordinate values from the
294         * lower and upper corner may be used instead than the minimum and maximum values, with the
295         * periodicity (360° for longitudes) added to the upper value before to perform the span
296         * calculation.
297         * <p>
298         * Implementations are free to use variants of the above algorithm. For example some
299         * libraries may add different multiples of the periodicity.</font></blockquote>
300         *
301         * @param  dimension The dimension for which to obtain the span.
302         * @return The span (typically width or height) at the given dimension.
303         * @throws IndexOutOfBoundsException If the given index is negative or is equals or greater
304         *         than the {@linkplain #getDimension() envelope dimension}.
305         *
306         * @departure easeOfUse
307         *   This method is not part of ISO specification. GeoAPI adds this method for convenience and
308         *   efficiency, since some implementations might store the span values directly in the
309         *   <code>Envelope</code> itself rather than calculating it from the corners.
310         *
311         * @see Rectangle2D#getWidth()
312         * @see Rectangle2D#getHeight()
313         *
314         * @since 2.2
315         */
316        double getSpan(int dimension) throws IndexOutOfBoundsException;
317    }