001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data;
003
004import org.openstreetmap.josm.data.coor.ILatLon;
005import org.openstreetmap.josm.data.coor.LatLon;
006
007/**
008 * Represents a "rectangular" area of the world, given in lat/lon min/max values.
009 *
010 * @since 17703
011 */
012public interface IBounds {
013
014    /**
015     * Gets the point that has both the minimal lat and lon coordinate
016     *
017     * @return The point
018     */
019    default ILatLon getMin() {
020        return new LatLon(getMinLat(), getMinLon());
021    }
022
023    /**
024     * Returns min latitude of bounds. Efficient shortcut for {@code getMin().lat()}.
025     *
026     * @return min latitude of bounds.
027     */
028    double getMinLat();
029
030    /**
031     * Returns min longitude of bounds. Efficient shortcut for {@code getMin().lon()}.
032     *
033     * @return min longitude of bounds.
034     */
035    double getMinLon();
036
037    /**
038     * Gets the point that has both the maximum lat and lon coordinate
039     *
040     * @return The point
041     */
042    default ILatLon getMax() {
043        return new LatLon(getMaxLat(), getMaxLon());
044    }
045
046    /**
047     * Returns max latitude of bounds. Efficient shortcut for {@code getMax().lat()}.
048     *
049     * @return max latitude of bounds.
050     */
051    double getMaxLat();
052
053    /**
054     * Returns max longitude of bounds. Efficient shortcut for {@code getMax().lon()}.
055     *
056     * @return max longitude of bounds.
057     */
058    double getMaxLon();
059
060    /**
061     * Returns center of the bounding box.
062     *
063     * @return Center of the bounding box.
064     */
065    ILatLon getCenter();
066
067    /**
068     * Determines if the given point {@code ll} is within these bounds.
069     * <p>
070     * Points with unknown coordinates are always outside the coordinates.
071     *
072     * @param ll The lat/lon to check
073     * @return {@code true} if {@code ll} is within these bounds, {@code false} otherwise
074     */
075    default boolean contains(ILatLon ll) {
076        return getMinLon() <= ll.lon() && ll.lon() <= getMaxLon()
077                && getMinLat() <= ll.lat() && ll.lat() <= getMaxLat();
078    }
079
080    /**
081     * Tests, whether the bbox {@code b} lies completely inside this bbox.
082     *
083     * @param b bounding box
084     * @return {@code true} if {@code b} lies completely inside this bbox
085     */
086    default boolean contains(IBounds b) {
087        return getMinLon() <= b.getMinLon() && getMaxLon() >= b.getMaxLon()
088                && getMinLat() <= b.getMinLat() && getMaxLat() >= b.getMaxLat();
089    }
090
091    /**
092     * The two bounds intersect? Compared to java Shape.intersects, if does not use
093     * the interior but the closure. ("&gt;=" instead of "&gt;")
094     *
095     * @param b other bounds
096     * @return {@code true} if the two bounds intersect
097     */
098    default boolean intersects(IBounds b) {
099        return getMinLon() <= b.getMaxLon() && getMaxLon() >= b.getMinLon()
100                && getMinLat() <= b.getMaxLat() && getMaxLat() >= b.getMinLat();
101    }
102
103    /**
104     * Returns the bounds width.
105     *
106     * @return the bounds width
107     */
108    double getHeight();
109
110    /**
111     * Returns the bounds width.
112     *
113     * @return the bounds width
114     */
115    double getWidth();
116
117    /**
118     * Gets the area of this bounds (in lat/lon space)
119     *
120     * @return The area
121     */
122    default double getArea() {
123        return getWidth() * getHeight();
124    }
125
126    /**
127     * Determines if the bbox covers a part of the planet surface.
128     *
129     * @return true if the bbox covers a part of the planet surface.
130     * Height and width must be non-negative, but may (both) be 0.
131     */
132    default boolean isValid() {
133        return true;
134    }
135
136    /**
137     * Determines if this Bounds object crosses the 180th Meridian.
138     * See http://wiki.openstreetmap.org/wiki/180th_meridian
139     *
140     * @return true if this Bounds object crosses the 180th Meridian.
141     */
142    default boolean crosses180thMeridian() {
143        return false;
144    }
145}