001 /*
002 * GeoAPI - Java interfaces for OGC/ISO standards
003 * http://www.geoapi.org
004 *
005 * Copyright (C) 2006-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; // For javadoc
035 import org.opengis.referencing.cs.AxisDirection; // For javadoc
036 import org.opengis.metadata.extent.GeographicBoundingBox; // For javadoc
037 import org.opengis.referencing.crs.GeographicCRS; // For javadoc
038 import org.opengis.referencing.crs.CRSAuthorityFactory; // For javadoc
039 import org.opengis.referencing.crs.CoordinateReferenceSystem;
040 import org.opengis.referencing.operation.TransformException;
041 import org.opengis.annotation.Extension;
042
043
044 /**
045 * Represents a two-dimensional {@linkplain Envelope envelope}.
046 * This interface combines the ideas of {@link GeographicBoundingBox} with
047 * those of {@link Envelope}. It provides convenience methods to assist
048 * in accessing the formal properties of this object. Those methods
049 * (for example {@link #getMinX()}) match common usage in existing libraries
050 * like {@linkplain Rectangle2D Java2D}.
051 * <p>
052 * This object contains no additional information beyond that provided
053 * by {@link Envelope}.
054 *
055 * @author Jody Garnett (Refractions Research)
056 * @author Martin Desruisseaux (Geomatys)
057 * @since GeoAPI 2.1
058 */
059 @Extension
060 public interface BoundingBox extends Envelope {
061 /**
062 * Sets this bounding box to be the same as the specified box.
063 *
064 * @param bounds The new bounds.
065 */
066 void setBounds(BoundingBox bounds);
067
068 /**
069 * Provides the minimum ordinate along the first axis.
070 * This is equivalent to <code>{@linkplain #getMinimum getMinimum}(0)</code>.
071 * There is no guarantee that this axis is oriented toward
072 * {@linkplain AxisDirection#EAST East}.
073 *
074 * @return The minimum ordinate along the first axis.
075 */
076 double getMinX();
077
078 /**
079 * Provides the maximum ordinate along the first axis.
080 * This is equivalent to <code>{@linkplain #getMaximum getMaximum}(0)</code>.
081 * There is no guarantee that this axis is oriented toward
082 * {@linkplain AxisDirection#EAST East}.
083 *
084 * @return The maximum ordinate along the first axis.
085 */
086 double getMaxX();
087
088 /**
089 * Provides the minimum ordinate along the second axis.
090 * This is equivalent to <code>{@linkplain #getMinimum getMinimum}(1)</code>.
091 * There is no guarantee that this axis is oriented toward
092 * {@linkplain AxisDirection#NORTH North}.
093 *
094 * @return The minimum ordinate along the second axis.
095 */
096 double getMinY();
097
098 /**
099 * Provides the maximum ordinate along the second axis.
100 * This is equivalent to <code>{@linkplain #getMaximum getMaximum}(1)</code>.
101 * There is no guarantee that this axis is oriented toward
102 * {@linkplain AxisDirection#NORTH North}.
103 *
104 * @return The maximum ordinate along the second axis.
105 */
106 double getMaxY();
107
108 /**
109 * Provides the difference between {@linkplain #getMinX minimum} and
110 * {@linkplain #getMaxX maximum} ordinate along the first axis.
111 * This is equivalent to <code>{@linkplain #getLength getLength}(0)</code>.
112 * There is no guarantee that this axis is oriented toward
113 * {@linkplain AxisDirection#EAST East}.
114 *
115 * @return The span along the first axis.
116 */
117 double getWidth();
118
119 /**
120 * Provides the difference between {@linkplain #getMinX minimum} and
121 * {@linkplain #getMaxX maximum} ordinate along the second axis.
122 * This is equivalent to <code>{@linkplain #getLength getLength}(1)</code>.
123 * There is no guarantee that this axis is oriented toward
124 * {@linkplain AxisDirection#NORTH North}.
125 *
126 * @return The span along the second axis.
127 */
128 double getHeight();
129
130 /**
131 * Returns {@code true} if {@linkplain #getSpan spans} along all dimension are zero
132 * or negative.
133 *
134 * @return {@code true} if this bounding box is empty.
135 */
136 boolean isEmpty();
137
138 /**
139 * Includes the provided bounding box, expanding as necesary.
140 *
141 * @param bounds The bounds to add to this geographic bounding box.
142 */
143 void include(BoundingBox bounds);
144
145 /**
146 * Includes the provided coordinates, expanding as necessary. Note that there is no
147 * guarantee that the (<var>x</var>, <var>x</var>) values are oriented toward
148 * ({@linkplain AxisDirection#EAST East}, {@linkplain AxisDirection#NORTH North}),
149 * since it depends on the {@linkplain #getCoordinateReferenceSystem envelope CRS}.
150 *
151 * @param x The first ordinate value.
152 * @param y The second ordinate value.
153 */
154 void include(double x, double y);
155
156 /**
157 * Returns {@code true} if the interior of this bounds intersects the interior
158 * of the provided bounds.
159 *
160 * @param bounds The bounds to test for intersection.
161 * @return {@code true} if the two bounds intersect.
162 */
163 boolean intersects(BoundingBox bounds);
164
165 /**
166 * Returns {@code true} if the provided bounds are contained by this bounding box.
167 *
168 * @param bounds The bounds to test for inclusion.
169 * @return {@code true} if the given bounds is inside this bounds.
170 */
171 boolean contains(BoundingBox bounds);
172
173 /**
174 * Returns {@code true} if the provided location is contained by this bounding box.
175 *
176 * @param location The direct position to test for inclusion.
177 * @return {@code true} if the given position is inside this bounds.
178 */
179 boolean contains(DirectPosition location);
180
181 /**
182 * Returns {@code true} if the provided location is contained by this bounding box.
183 * Note that there is no guarantee that the (<var>x</var>, <var>x</var>) values are
184 * oriented toward ({@linkplain AxisDirection#EAST East}, {@linkplain AxisDirection#NORTH North}),
185 * since it depends on the {@linkplain #getCoordinateReferenceSystem envelope CRS}.
186 *
187 * @param x The first ordinate value.
188 * @param y The second ordinate value.
189 * @return {@code true} if the given position is inside this bounds.
190 */
191 boolean contains(double x, double y);
192
193 /**
194 * Transforms this box to the specified CRS and returns a new bounding box for the
195 * transformed shape. This method provides a convenient (while not always efficient)
196 * way to get {@linkplain #getMinimum minimum} and {@linkplain #getMaximum maximum}
197 * ordinate values toward some specific axis directions, typically
198 * {@linkplain AxisDirection#EAST East} and {@linkplain AxisDirection#NORTH North}.
199 * <p>
200 * <b>Example:</b> if {@code box} is a bounding box using a {@linkplain GeographicCRS
201 * geographic CRS} with WGS84 datum, then one can write:
202 *
203 * <blockquote><pre>
204 * GeographicCRS targetCRS = crsAuthorityFactory.{@linkplain CRSAuthorityFactory#createGeographicCRS createGeographicCRS}("EPSG:4326");
205 * BoundingBox targetBox = box.toBounds(targetCRS);
206 * double minEasting = targetBox.getMinY();
207 * double minNorthing = targetBox.getMinX();
208 * </pre></blockquote>
209 *
210 * Be aware that {@code "EPSG:4326"} has (<var>latitude</var>, <var>longitude</var>)
211 * axis order, thus the inversion of <var>X</var> and <var>Y</var> in the above code.
212 * <p>
213 * Sophesticated applications will typically provide more efficient way to perform
214 * similar transformations in their context. For example {@linkplain Canvas} store
215 * precomputed {@linkplain Canvas#getObjectiveToDisplayTransform objective to display
216 * transforms}.
217 *
218 * @param targetCRS The target CRS for the bounding box to be returned.
219 * @return A new bounding box wich includes the shape of this box transformed
220 * to the specified target CRS.
221 * @throws TransformException if no transformation path has been found from
222 * {@linkplain #getCoordinateReferenceSystem this box CRS} to the specified
223 * target CRS, or if the transformation failed for an other reason.
224 */
225 BoundingBox toBounds(CoordinateReferenceSystem targetCRS) throws TransformException;
226 }