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> < <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> > <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> < <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> < <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 }