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. (">=" instead of ">") 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}