You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

193 lines
6.1 KiB
C++

// 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__