2014-11-28 06:13:18 -05:00
|
|
|
#ifndef RECTANGLE_HPP
|
|
|
|
#define RECTANGLE_HPP
|
2014-10-28 19:33:43 -04:00
|
|
|
|
2016-01-02 11:13:44 -05:00
|
|
|
#include "util/coordinate_calculation.hpp"
|
2015-01-20 10:24:49 -05:00
|
|
|
|
2014-10-28 19:33:43 -04:00
|
|
|
#include <boost/assert.hpp>
|
|
|
|
|
2016-01-02 11:13:44 -05:00
|
|
|
#include "osrm/coordinate.hpp"
|
2015-02-10 06:34:13 -05:00
|
|
|
|
2014-10-28 19:33:43 -04:00
|
|
|
#include <algorithm>
|
2016-02-26 07:59:16 -05:00
|
|
|
#include <utility>
|
2014-10-28 19:33:43 -04:00
|
|
|
#include <limits>
|
|
|
|
|
2016-02-26 07:59:16 -05:00
|
|
|
#include <cstdint>
|
|
|
|
|
2016-01-05 10:51:13 -05:00
|
|
|
namespace osrm
|
|
|
|
{
|
|
|
|
namespace util
|
|
|
|
{
|
|
|
|
|
2014-10-28 19:33:43 -04:00
|
|
|
// TODO: Make template type, add tests
|
|
|
|
struct RectangleInt2D
|
|
|
|
{
|
2015-02-10 06:29:52 -05:00
|
|
|
RectangleInt2D()
|
2016-02-26 08:01:54 -05:00
|
|
|
: min_lon(std::numeric_limits<std::int32_t>::max()),
|
|
|
|
max_lon(std::numeric_limits<std::int32_t>::min()),
|
|
|
|
min_lat(std::numeric_limits<std::int32_t>::max()),
|
|
|
|
max_lat(std::numeric_limits<std::int32_t>::min())
|
2015-02-10 06:29:52 -05:00
|
|
|
{
|
|
|
|
}
|
2014-10-28 19:33:43 -04:00
|
|
|
|
2016-02-26 08:01:54 -05:00
|
|
|
RectangleInt2D(std::int32_t min_lon_,
|
|
|
|
std::int32_t max_lon_,
|
|
|
|
std::int32_t min_lat_,
|
|
|
|
std::int32_t max_lat_)
|
2016-02-26 06:29:57 -05:00
|
|
|
: min_lon(min_lon_), max_lon(max_lon_), min_lat(min_lat_), max_lat(max_lat_)
|
|
|
|
{
|
|
|
|
}
|
2016-02-16 13:51:04 -05:00
|
|
|
|
2016-02-26 08:01:54 -05:00
|
|
|
std::int32_t min_lon, max_lon;
|
|
|
|
std::int32_t min_lat, max_lat;
|
2014-10-28 19:33:43 -04:00
|
|
|
|
2015-02-10 06:29:52 -05:00
|
|
|
void MergeBoundingBoxes(const RectangleInt2D &other)
|
2014-10-28 19:33:43 -04:00
|
|
|
{
|
|
|
|
min_lon = std::min(min_lon, other.min_lon);
|
|
|
|
max_lon = std::max(max_lon, other.max_lon);
|
|
|
|
min_lat = std::min(min_lat, other.min_lat);
|
|
|
|
max_lat = std::max(max_lat, other.max_lat);
|
2016-02-26 08:01:54 -05:00
|
|
|
BOOST_ASSERT(min_lat != std::numeric_limits<std::int32_t>::min());
|
|
|
|
BOOST_ASSERT(min_lon != std::numeric_limits<std::int32_t>::min());
|
|
|
|
BOOST_ASSERT(max_lat != std::numeric_limits<std::int32_t>::min());
|
|
|
|
BOOST_ASSERT(max_lon != std::numeric_limits<std::int32_t>::min());
|
2014-10-28 19:33:43 -04:00
|
|
|
}
|
|
|
|
|
2015-02-10 06:29:52 -05:00
|
|
|
FixedPointCoordinate Centroid() const
|
2014-10-28 19:33:43 -04:00
|
|
|
{
|
|
|
|
FixedPointCoordinate centroid;
|
|
|
|
// The coordinates of the midpoints are given by:
|
|
|
|
// x = (x1 + x2) /2 and y = (y1 + y2) /2.
|
|
|
|
centroid.lon = (min_lon + max_lon) / 2;
|
|
|
|
centroid.lat = (min_lat + max_lat) / 2;
|
|
|
|
return centroid;
|
|
|
|
}
|
|
|
|
|
2015-02-10 06:29:52 -05:00
|
|
|
bool Intersects(const RectangleInt2D &other) const
|
2014-10-28 19:33:43 -04:00
|
|
|
{
|
2016-02-16 13:51:04 -05:00
|
|
|
// Standard box intersection test - check if boxes *don't* overlap,
|
|
|
|
// and return the negative of that
|
2016-02-26 06:29:57 -05:00
|
|
|
return !(max_lon < other.min_lon || min_lon > other.max_lon || max_lat < other.min_lat ||
|
|
|
|
min_lat > other.max_lat);
|
2014-10-28 19:33:43 -04:00
|
|
|
}
|
|
|
|
|
2016-01-21 07:07:24 -05:00
|
|
|
double GetMinDist(const FixedPointCoordinate location) const
|
2014-10-28 19:33:43 -04:00
|
|
|
{
|
|
|
|
const bool is_contained = Contains(location);
|
|
|
|
if (is_contained)
|
|
|
|
{
|
|
|
|
return 0.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum Direction
|
|
|
|
{
|
2015-02-10 06:29:52 -05:00
|
|
|
INVALID = 0,
|
|
|
|
NORTH = 1,
|
|
|
|
SOUTH = 2,
|
|
|
|
EAST = 4,
|
2014-10-28 19:33:43 -04:00
|
|
|
NORTH_EAST = 5,
|
|
|
|
SOUTH_EAST = 6,
|
2015-02-10 06:29:52 -05:00
|
|
|
WEST = 8,
|
2014-10-28 19:33:43 -04:00
|
|
|
NORTH_WEST = 9,
|
|
|
|
SOUTH_WEST = 10
|
|
|
|
};
|
|
|
|
|
|
|
|
Direction d = INVALID;
|
|
|
|
if (location.lat > max_lat)
|
2015-02-10 06:29:52 -05:00
|
|
|
d = (Direction)(d | NORTH);
|
2014-10-28 19:33:43 -04:00
|
|
|
else if (location.lat < min_lat)
|
2015-02-10 06:29:52 -05:00
|
|
|
d = (Direction)(d | SOUTH);
|
2014-10-28 19:33:43 -04:00
|
|
|
if (location.lon > max_lon)
|
2015-02-10 06:29:52 -05:00
|
|
|
d = (Direction)(d | EAST);
|
2014-10-28 19:33:43 -04:00
|
|
|
else if (location.lon < min_lon)
|
2015-02-10 06:29:52 -05:00
|
|
|
d = (Direction)(d | WEST);
|
2014-10-28 19:33:43 -04:00
|
|
|
|
|
|
|
BOOST_ASSERT(d != INVALID);
|
|
|
|
|
2015-12-26 14:12:10 -05:00
|
|
|
double min_dist = std::numeric_limits<double>::max();
|
2014-10-28 19:33:43 -04:00
|
|
|
switch (d)
|
|
|
|
{
|
2015-02-10 06:29:52 -05:00
|
|
|
case NORTH:
|
2016-01-04 07:30:03 -05:00
|
|
|
min_dist = coordinate_calculation::greatCircleDistance(
|
2015-02-10 06:29:52 -05:00
|
|
|
location, FixedPointCoordinate(max_lat, location.lon));
|
|
|
|
break;
|
|
|
|
case SOUTH:
|
2016-01-04 07:30:03 -05:00
|
|
|
min_dist = coordinate_calculation::greatCircleDistance(
|
2015-02-10 06:29:52 -05:00
|
|
|
location, FixedPointCoordinate(min_lat, location.lon));
|
|
|
|
break;
|
|
|
|
case WEST:
|
2016-01-04 07:30:03 -05:00
|
|
|
min_dist = coordinate_calculation::greatCircleDistance(
|
2015-02-10 06:29:52 -05:00
|
|
|
location, FixedPointCoordinate(location.lat, min_lon));
|
|
|
|
break;
|
|
|
|
case EAST:
|
2016-01-04 07:30:03 -05:00
|
|
|
min_dist = coordinate_calculation::greatCircleDistance(
|
2015-02-10 06:29:52 -05:00
|
|
|
location, FixedPointCoordinate(location.lat, max_lon));
|
|
|
|
break;
|
|
|
|
case NORTH_EAST:
|
2016-01-04 07:30:03 -05:00
|
|
|
min_dist = coordinate_calculation::greatCircleDistance(
|
2015-02-10 06:29:52 -05:00
|
|
|
location, FixedPointCoordinate(max_lat, max_lon));
|
|
|
|
break;
|
|
|
|
case NORTH_WEST:
|
2016-01-04 07:30:03 -05:00
|
|
|
min_dist = coordinate_calculation::greatCircleDistance(
|
2015-02-10 06:29:52 -05:00
|
|
|
location, FixedPointCoordinate(max_lat, min_lon));
|
|
|
|
break;
|
|
|
|
case SOUTH_EAST:
|
2016-01-04 07:30:03 -05:00
|
|
|
min_dist = coordinate_calculation::greatCircleDistance(
|
2015-02-10 06:29:52 -05:00
|
|
|
location, FixedPointCoordinate(min_lat, max_lon));
|
|
|
|
break;
|
|
|
|
case SOUTH_WEST:
|
2016-01-04 07:30:03 -05:00
|
|
|
min_dist = coordinate_calculation::greatCircleDistance(
|
2015-02-10 06:29:52 -05:00
|
|
|
location, FixedPointCoordinate(min_lat, min_lon));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2014-10-28 19:33:43 -04:00
|
|
|
}
|
|
|
|
|
2015-12-26 14:12:10 -05:00
|
|
|
BOOST_ASSERT(min_dist < std::numeric_limits<double>::max());
|
2014-10-28 19:33:43 -04:00
|
|
|
|
|
|
|
return min_dist;
|
|
|
|
}
|
|
|
|
|
2016-01-21 07:07:24 -05:00
|
|
|
double GetMinMaxDist(const FixedPointCoordinate location) const
|
2014-10-28 19:33:43 -04:00
|
|
|
{
|
2015-12-26 14:12:10 -05:00
|
|
|
double min_max_dist = std::numeric_limits<double>::max();
|
2014-10-28 19:33:43 -04:00
|
|
|
// Get minmax distance to each of the four sides
|
|
|
|
const FixedPointCoordinate upper_left(max_lat, min_lon);
|
|
|
|
const FixedPointCoordinate upper_right(max_lat, max_lon);
|
|
|
|
const FixedPointCoordinate lower_right(min_lat, max_lon);
|
|
|
|
const FixedPointCoordinate lower_left(min_lat, min_lon);
|
|
|
|
|
2016-01-07 19:31:57 -05:00
|
|
|
min_max_dist =
|
|
|
|
std::min(min_max_dist,
|
|
|
|
std::max(coordinate_calculation::greatCircleDistance(location, upper_left),
|
|
|
|
coordinate_calculation::greatCircleDistance(location, upper_right)));
|
2015-02-10 06:29:52 -05:00
|
|
|
|
2016-01-07 19:31:57 -05:00
|
|
|
min_max_dist =
|
|
|
|
std::min(min_max_dist,
|
|
|
|
std::max(coordinate_calculation::greatCircleDistance(location, upper_right),
|
|
|
|
coordinate_calculation::greatCircleDistance(location, lower_right)));
|
2015-02-10 06:29:52 -05:00
|
|
|
|
|
|
|
min_max_dist =
|
|
|
|
std::min(min_max_dist,
|
2016-01-04 07:30:03 -05:00
|
|
|
std::max(coordinate_calculation::greatCircleDistance(location, lower_right),
|
|
|
|
coordinate_calculation::greatCircleDistance(location, lower_left)));
|
2015-02-10 06:29:52 -05:00
|
|
|
|
|
|
|
min_max_dist =
|
|
|
|
std::min(min_max_dist,
|
2016-01-04 07:30:03 -05:00
|
|
|
std::max(coordinate_calculation::greatCircleDistance(location, lower_left),
|
|
|
|
coordinate_calculation::greatCircleDistance(location, upper_left)));
|
2014-10-28 19:33:43 -04:00
|
|
|
return min_max_dist;
|
|
|
|
}
|
|
|
|
|
2016-01-21 07:07:24 -05:00
|
|
|
bool Contains(const FixedPointCoordinate location) const
|
2014-10-28 19:33:43 -04:00
|
|
|
{
|
|
|
|
const bool lats_contained = (location.lat >= min_lat) && (location.lat <= max_lat);
|
|
|
|
const bool lons_contained = (location.lon >= min_lon) && (location.lon <= max_lon);
|
|
|
|
return lats_contained && lons_contained;
|
|
|
|
}
|
|
|
|
};
|
2016-01-05 10:51:13 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-28 19:33:43 -04:00
|
|
|
#endif
|