1 // Copyright 2008, Google Inc. All rights reserved. 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are met: 5 // 6 // 1. Redistributions of source code must retain the above copyright notice, 7 // this list of conditions and the following disclaimer. 8 // 2. Redistributions in binary form must reproduce the above copyright notice, 9 // this list of conditions and the following disclaimer in the documentation 10 // and/or other materials provided with the distribution. 11 // 3. Neither the name of Google Inc. nor the names of its contributors may be 12 // used to endorse or promote products derived from this software without 13 // specific prior written permission. 14 // 15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 26 // This file contains the definition of the Bbox class. 27 28 #ifndef KML_ENGINE_BBOX_H__ 29 #define KML_ENGINE_BBOX_H__ 30 31 namespace kmlengine { 32 33 const double kMinLat = -180.0; 34 const double kMaxLat = 180.0; 35 const double kMinLon = -180.0; 36 const double kMaxLon = 180.0; 37 38 // This class maintains a simple geographic bounding box. Example usage: 39 // Bbox bbox; 40 // bbox.ExpandLatLon(lat, lon); // 0 or more times for a set of lat,lon. 41 // 42 // // Inquire some things about the bounding box: 43 // double mid_lat, mid_lon; 44 // bbox.GetCenter(&mid_lat, &mid_lon); 45 // double north = bbox.get_north() // Same for s,e,w 46 // bool contains = bbox.Contains(lat, lon); 47 // 48 // NOTE: There is no provision for the ante-meridian nor for the validity 49 // of any latitude or longitude value. 50 class Bbox { 51 public: 52 // Construct a default bounding box. The mininums and maximums are set such 53 // that any valid latitude/longitude are handled properly. Bbox()54 Bbox() : north_(kMinLat), south_(kMaxLat), east_(kMinLon), west_(kMaxLon) {} 55 56 // Construct a bounding box of a given extent. There are no checks for 57 // the validity of these parameters. Bbox(double north,double south,double east,double west)58 Bbox(double north, double south, double east, double west) 59 : north_(north), south_(south), east_(east), west_(west) {} 60 61 // This aligns this Bbox within the quadtree specified down to the maximum 62 // level specified. AlignBbox(Bbox * qt,unsigned int max_depth)63 void AlignBbox(Bbox* qt, unsigned int max_depth) { 64 if (!qt) { 65 return; 66 } 67 double lat = qt->GetCenterLat(); 68 double lon = qt->GetCenterLon(); 69 if (ContainedByBox(qt->get_north(), lat, qt->get_east(), lon)) { 70 qt->set_south(lat); 71 qt->set_west(lon); 72 } else if (ContainedByBox(qt->get_north(), lat, lon, qt->get_west())) { 73 qt->set_south(lat); 74 qt->set_east(lon); 75 } else if (ContainedByBox(lat, qt->get_south(), qt->get_east(), lon)) { 76 qt->set_north(lat); 77 qt->set_west(lon); 78 } else if (ContainedByBox(lat, qt->get_south(), lon, qt->get_west())) { 79 qt->set_north(lat); 80 qt->set_east(lon); 81 } else { 82 return; // target not contained by any child quadrant of qt. 83 } 84 // Fall through from above and recurse. 85 if (max_depth > 0) { 86 AlignBbox(qt, max_depth - 1); 87 } 88 } 89 90 // This returns true if this Bbox is contained by the given Bbox. ContainedByBbox(const Bbox & b)91 bool ContainedByBbox(const Bbox& b) const { 92 return ContainedByBox(b.get_north(), b.get_south(), b.get_east(), 93 b.get_west()); 94 } 95 96 // This returns true of this Bbox is contained with the given bounds. ContainedByBox(double north,double south,double east,double west)97 bool ContainedByBox(double north, double south, 98 double east, double west) const { 99 return north >= north_ && south <= south_ && east >= east_ && west <= west_; 100 } 101 102 // This returns true if the bbox contains the given latitude,longitude. Contains(double latitude,double longitude)103 bool Contains(double latitude, double longitude) const { 104 return north_ >= latitude && south_ <= latitude && 105 east_ >= longitude && west_ <= longitude; 106 } 107 108 // This expands this Bbox to contain the given Bbox. ExpandFromBbox(const Bbox & bbox)109 void ExpandFromBbox(const Bbox& bbox) { 110 ExpandLatitude(bbox.get_north()); 111 ExpandLatitude(bbox.get_south()); 112 ExpandLongitude(bbox.get_east()); 113 ExpandLongitude(bbox.get_west()); 114 } 115 116 // This expands the bounding box to include the given latitude. ExpandLatitude(double latitude)117 void ExpandLatitude(double latitude) { 118 if (latitude > north_) { 119 north_ = latitude; 120 } 121 if (latitude < south_) { 122 south_ = latitude; 123 } 124 } 125 126 // This expands the bounding box to include the given longitude. ExpandLongitude(double longitude)127 void ExpandLongitude(double longitude) { 128 if (longitude > east_) { 129 east_ = longitude; 130 } 131 if (longitude < west_) { 132 west_ = longitude; 133 } 134 } 135 136 // This expands the bounding box to include the given latitude and longitude. ExpandLatLon(double latitude,double longitude)137 void ExpandLatLon(double latitude, double longitude) { 138 ExpandLatitude(latitude); 139 ExpandLongitude(longitude); 140 } 141 get_north()142 double get_north() const { 143 return north_; 144 } get_south()145 double get_south() const { 146 return south_; 147 } get_east()148 double get_east() const { 149 return east_; 150 } get_west()151 double get_west() const { 152 return west_; 153 } 154 155 // This returns the center of the bounding box. GetCenter(double * latitude,double * longitude)156 void GetCenter(double* latitude, double* longitude) const { 157 if (latitude) { 158 *latitude = GetCenterLat(); 159 } 160 if (longitude) { 161 *longitude = GetCenterLon(); 162 } 163 } 164 GetCenterLat()165 double GetCenterLat() const { 166 return (north_ + south_)/2.0; 167 } 168 GetCenterLon()169 double GetCenterLon() const { 170 return (east_ + west_)/2.0; 171 } 172 set_north(double n)173 void set_north(double n) { 174 north_ = n; 175 } set_south(double s)176 void set_south(double s) { 177 south_ = s; 178 } set_east(double e)179 void set_east(double e) { 180 east_ = e; 181 } set_west(double w)182 void set_west(double w) { 183 west_ = w; 184 } 185 186 private: 187 double north_, south_, east_, west_; 188 }; 189 190 } // end namespace kmlengine 191 192 #endif // KML_ENGINE_BBOX_H__ 193