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
193 lines
6.1 KiB
C
2 years ago
|
// 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__
|