// Copyright 2008, Google Inc. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // 3. Neither the name of Google Inc. nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // This file contains the definition of the Bbox class. #ifndef KML_ENGINE_BBOX_H__ #define KML_ENGINE_BBOX_H__ namespace kmlengine { const double kMinLat = -180.0; const double kMaxLat = 180.0; const double kMinLon = -180.0; const double kMaxLon = 180.0; // This class maintains a simple geographic bounding box. Example usage: // Bbox bbox; // bbox.ExpandLatLon(lat, lon); // 0 or more times for a set of lat,lon. // // // Inquire some things about the bounding box: // double mid_lat, mid_lon; // bbox.GetCenter(&mid_lat, &mid_lon); // double north = bbox.get_north() // Same for s,e,w // bool contains = bbox.Contains(lat, lon); // // NOTE: There is no provision for the ante-meridian nor for the validity // of any latitude or longitude value. class Bbox { public: // Construct a default bounding box. The mininums and maximums are set such // that any valid latitude/longitude are handled properly. Bbox() : north_(kMinLat), south_(kMaxLat), east_(kMinLon), west_(kMaxLon) {} // Construct a bounding box of a given extent. There are no checks for // the validity of these parameters. Bbox(double north, double south, double east, double west) : north_(north), south_(south), east_(east), west_(west) {} // This aligns this Bbox within the quadtree specified down to the maximum // level specified. void AlignBbox(Bbox* qt, unsigned int max_depth) { if (!qt) { return; } double lat = qt->GetCenterLat(); double lon = qt->GetCenterLon(); if (ContainedByBox(qt->get_north(), lat, qt->get_east(), lon)) { qt->set_south(lat); qt->set_west(lon); } else if (ContainedByBox(qt->get_north(), lat, lon, qt->get_west())) { qt->set_south(lat); qt->set_east(lon); } else if (ContainedByBox(lat, qt->get_south(), qt->get_east(), lon)) { qt->set_north(lat); qt->set_west(lon); } else if (ContainedByBox(lat, qt->get_south(), lon, qt->get_west())) { qt->set_north(lat); qt->set_east(lon); } else { return; // target not contained by any child quadrant of qt. } // Fall through from above and recurse. if (max_depth > 0) { AlignBbox(qt, max_depth - 1); } } // This returns true if this Bbox is contained by the given Bbox. bool ContainedByBbox(const Bbox& b) const { return ContainedByBox(b.get_north(), b.get_south(), b.get_east(), b.get_west()); } // This returns true of this Bbox is contained with the given bounds. bool ContainedByBox(double north, double south, double east, double west) const { return north >= north_ && south <= south_ && east >= east_ && west <= west_; } // This returns true if the bbox contains the given latitude,longitude. bool Contains(double latitude, double longitude) const { return north_ >= latitude && south_ <= latitude && east_ >= longitude && west_ <= longitude; } // This expands this Bbox to contain the given Bbox. void ExpandFromBbox(const Bbox& bbox) { ExpandLatitude(bbox.get_north()); ExpandLatitude(bbox.get_south()); ExpandLongitude(bbox.get_east()); ExpandLongitude(bbox.get_west()); } // This expands the bounding box to include the given latitude. void ExpandLatitude(double latitude) { if (latitude > north_) { north_ = latitude; } if (latitude < south_) { south_ = latitude; } } // This expands the bounding box to include the given longitude. void ExpandLongitude(double longitude) { if (longitude > east_) { east_ = longitude; } if (longitude < west_) { west_ = longitude; } } // This expands the bounding box to include the given latitude and longitude. void ExpandLatLon(double latitude, double longitude) { ExpandLatitude(latitude); ExpandLongitude(longitude); } double get_north() const { return north_; } double get_south() const { return south_; } double get_east() const { return east_; } double get_west() const { return west_; } // This returns the center of the bounding box. void GetCenter(double* latitude, double* longitude) const { if (latitude) { *latitude = GetCenterLat(); } if (longitude) { *longitude = GetCenterLon(); } } double GetCenterLat() const { return (north_ + south_)/2.0; } double GetCenterLon() const { return (east_ + west_)/2.0; } void set_north(double n) { north_ = n; } void set_south(double s) { south_ = s; } void set_east(double e) { east_ = e; } void set_west(double w) { west_ = w; } private: double north_, south_, east_, west_; }; } // end namespace kmlengine #endif // KML_ENGINE_BBOX_H__