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    }