speed up nearest neighbor query by pruning, move coordinate calculations away from library interface
This commit is contained in:
parent
8f813fbc67
commit
01f3237416
@ -72,7 +72,7 @@ file(GLOB ServerGlob Server/*.cpp)
|
||||
file(GLOB DescriptorGlob descriptors/*.cpp)
|
||||
file(GLOB DatastructureGlob data_structures/search_engine_data.cpp data_structures/route_parameters.cpp Util/bearing.cpp)
|
||||
list(REMOVE_ITEM DatastructureGlob data_structures/Coordinate.cpp)
|
||||
file(GLOB CoordinateGlob data_structures/coordinate.cpp)
|
||||
file(GLOB CoordinateGlob data_structures/coordinate*.cpp)
|
||||
file(GLOB AlgorithmGlob algorithms/*.cpp)
|
||||
file(GLOB HttpGlob Server/Http/*.cpp)
|
||||
file(GLOB LibOSRMGlob Library/*.cpp)
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -36,6 +36,7 @@ namespace
|
||||
{
|
||||
constexpr static const float COORDINATE_PRECISION = 1000000.f;
|
||||
}
|
||||
|
||||
struct FixedPointCoordinate
|
||||
{
|
||||
int lat;
|
||||
@ -56,52 +57,8 @@ struct FixedPointCoordinate
|
||||
bool is_valid() const;
|
||||
bool operator==(const FixedPointCoordinate &other) const;
|
||||
|
||||
static double
|
||||
ApproximateDistance(const int lat1, const int lon1, const int lat2, const int lon2);
|
||||
|
||||
static double ApproximateDistance(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate);
|
||||
|
||||
static float ApproximateEuclideanDistance(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate);
|
||||
|
||||
static float
|
||||
ApproximateEuclideanDistance(const int lat1, const int lon1, const int lat2, const int lon2);
|
||||
|
||||
static float ApproximateSquaredEuclideanDistance(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate);
|
||||
|
||||
static void convertInternalLatLonToString(const int value, std::string &output);
|
||||
|
||||
static void convertInternalCoordinateToString(const FixedPointCoordinate &coordinate,
|
||||
std::string &output);
|
||||
|
||||
static void convertInternalReversedCoordinateToString(const FixedPointCoordinate &coordinate,
|
||||
std::string &output);
|
||||
|
||||
static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location);
|
||||
|
||||
static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
float &ratio);
|
||||
|
||||
static int
|
||||
OrderedPerpendicularDistanceApproximation(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location);
|
||||
|
||||
static float GetBearing(const FixedPointCoordinate &A, const FixedPointCoordinate &B);
|
||||
|
||||
float GetBearing(const FixedPointCoordinate &other) const;
|
||||
|
||||
void Output(std::ostream &out) const;
|
||||
|
||||
static float DegreeToRadian(const float degree);
|
||||
static float RadianToDegree(const float radian);
|
||||
};
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &out_stream, FixedPointCoordinate const &coordinate)
|
||||
|
@ -25,20 +25,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "coordinate_calculation.hpp"
|
||||
|
||||
#include "../Util/mercator.hpp"
|
||||
#ifndef NDEBUG
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#endif
|
||||
#include "../Util/string_util.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include <bitset>
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
FixedPointCoordinate::FixedPointCoordinate()
|
||||
@ -87,235 +86,21 @@ bool FixedPointCoordinate::operator==(const FixedPointCoordinate &other) const
|
||||
return lat == other.lat && lon == other.lon;
|
||||
}
|
||||
|
||||
double FixedPointCoordinate::ApproximateDistance(const int lat1,
|
||||
const int lon1,
|
||||
const int lat2,
|
||||
const int lon2)
|
||||
{
|
||||
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||
double RAD = 0.017453292519943295769236907684886;
|
||||
double lt1 = lat1 / COORDINATE_PRECISION;
|
||||
double ln1 = lon1 / COORDINATE_PRECISION;
|
||||
double lt2 = lat2 / COORDINATE_PRECISION;
|
||||
double ln2 = lon2 / COORDINATE_PRECISION;
|
||||
double dlat1 = lt1 * (RAD);
|
||||
|
||||
double dlong1 = ln1 * (RAD);
|
||||
double dlat2 = lt2 * (RAD);
|
||||
double dlong2 = ln2 * (RAD);
|
||||
|
||||
double dLong = dlong1 - dlong2;
|
||||
double dLat = dlat1 - dlat2;
|
||||
|
||||
double aHarv = pow(sin(dLat / 2.0), 2.0) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2.), 2);
|
||||
double cHarv = 2. * atan2(sqrt(aHarv), sqrt(1.0 - aHarv));
|
||||
// earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
|
||||
// The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
|
||||
const double earth = 6372797.560856;
|
||||
return earth * cHarv;
|
||||
}
|
||||
|
||||
double FixedPointCoordinate::ApproximateDistance(const FixedPointCoordinate &coordinate_1,
|
||||
const FixedPointCoordinate &coordinate_2)
|
||||
{
|
||||
return ApproximateDistance(
|
||||
coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::ApproximateEuclideanDistance(const FixedPointCoordinate &coordinate_1,
|
||||
const FixedPointCoordinate &coordinate_2)
|
||||
{
|
||||
return ApproximateEuclideanDistance(
|
||||
coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::ApproximateEuclideanDistance(const int lat1,
|
||||
const int lon1,
|
||||
const int lat2,
|
||||
const int lon2)
|
||||
{
|
||||
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||
|
||||
const float RAD = 0.017453292519943295769236907684886f;
|
||||
const float float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD;
|
||||
const float float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD;
|
||||
const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD;
|
||||
const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD;
|
||||
|
||||
const float x_value = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.f);
|
||||
const float y_value = float_lat2 - float_lat1;
|
||||
const float earth_radius = 6372797.560856f;
|
||||
return sqrt(x_value * x_value + y_value * y_value) * earth_radius;
|
||||
}
|
||||
|
||||
float
|
||||
FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &source_coordinate,
|
||||
const FixedPointCoordinate &target_coordinate,
|
||||
const FixedPointCoordinate &query_location)
|
||||
{
|
||||
float ratio;
|
||||
FixedPointCoordinate nearest_location;
|
||||
|
||||
return ComputePerpendicularDistance(source_coordinate,
|
||||
target_coordinate,
|
||||
query_location,
|
||||
nearest_location,
|
||||
ratio);
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
float &ratio)
|
||||
{
|
||||
BOOST_ASSERT(query_location.is_valid());
|
||||
|
||||
// initialize values
|
||||
const double x = mercator::lat2y(query_location.lat / COORDINATE_PRECISION);
|
||||
const double y = query_location.lon / COORDINATE_PRECISION;
|
||||
const double a = mercator::lat2y(segment_source.lat / COORDINATE_PRECISION);
|
||||
const double b = segment_source.lon / COORDINATE_PRECISION;
|
||||
const double c = mercator::lat2y(segment_target.lat / COORDINATE_PRECISION);
|
||||
const double d = segment_target.lon / COORDINATE_PRECISION;
|
||||
double p, q /*,mX*/, nY;
|
||||
if (std::abs(a - c) > std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
const double m = (d - b) / (c - a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
|
||||
q = b + m * (p - a);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
nY = (d * p - c * q) / (a * d - b * c);
|
||||
|
||||
// discretize the result to coordinate precision. it's a hack!
|
||||
if (std::abs(nY) < (1.f / COORDINATE_PRECISION))
|
||||
{
|
||||
nY = 0.f;
|
||||
}
|
||||
|
||||
// compute ratio
|
||||
ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need
|
||||
// not calculate the explicit values of m an n as we
|
||||
// are just interested in the ratio
|
||||
if (std::isnan(ratio))
|
||||
{
|
||||
ratio = (segment_target == query_location ? 1.f : 0.f);
|
||||
}
|
||||
else if (std::abs(ratio) <= std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
ratio = 0.f;
|
||||
}
|
||||
else if (std::abs(ratio - 1.f) <= std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
ratio = 1.f;
|
||||
}
|
||||
|
||||
// compute nearest location
|
||||
BOOST_ASSERT(!std::isnan(ratio));
|
||||
if (ratio <= 0.f)
|
||||
{
|
||||
nearest_location = segment_source;
|
||||
}
|
||||
else if (ratio >= 1.f)
|
||||
{
|
||||
nearest_location = segment_target;
|
||||
}
|
||||
else
|
||||
{
|
||||
// point lies in between
|
||||
nearest_location.lat = static_cast<int>(mercator::y2lat(p) * COORDINATE_PRECISION);
|
||||
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
|
||||
}
|
||||
BOOST_ASSERT(nearest_location.is_valid());
|
||||
|
||||
const float approximate_distance =
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(query_location, nearest_location);
|
||||
BOOST_ASSERT(0. <= approximate_distance);
|
||||
return approximate_distance;
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::convertInternalLatLonToString(const int value, std::string &output)
|
||||
{
|
||||
char buffer[12];
|
||||
buffer[11] = 0; // zero termination
|
||||
output = printInt<11, 6>(buffer, value);
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::convertInternalCoordinateToString(const FixedPointCoordinate &coord,
|
||||
std::string &output)
|
||||
{
|
||||
std::string tmp;
|
||||
tmp.reserve(23);
|
||||
convertInternalLatLonToString(coord.lon, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
convertInternalLatLonToString(coord.lat, tmp);
|
||||
output += tmp;
|
||||
}
|
||||
|
||||
void
|
||||
FixedPointCoordinate::convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord,
|
||||
std::string &output)
|
||||
{
|
||||
std::string tmp;
|
||||
tmp.reserve(23);
|
||||
convertInternalLatLonToString(coord.lat, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
convertInternalLatLonToString(coord.lon, tmp);
|
||||
output += tmp;
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::Output(std::ostream &out) const
|
||||
{
|
||||
out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")";
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate)
|
||||
{
|
||||
const float lon_diff =
|
||||
second_coordinate.lon / COORDINATE_PRECISION - first_coordinate.lon / COORDINATE_PRECISION;
|
||||
const float lon_delta = DegreeToRadian(lon_diff);
|
||||
const float lat1 = DegreeToRadian(first_coordinate.lat / COORDINATE_PRECISION);
|
||||
const float lat2 = DegreeToRadian(second_coordinate.lat / COORDINATE_PRECISION);
|
||||
const float y = sin(lon_delta) * cos(lat2);
|
||||
const float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon_delta);
|
||||
float result = RadianToDegree(std::atan2(y, x));
|
||||
while (result < 0.f)
|
||||
{
|
||||
result += 360.f;
|
||||
}
|
||||
|
||||
while (result >= 360.f)
|
||||
{
|
||||
result -= 360.f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &other) const
|
||||
{
|
||||
const float lon_delta =
|
||||
DegreeToRadian(lon / COORDINATE_PRECISION - other.lon / COORDINATE_PRECISION);
|
||||
const float lat1 = DegreeToRadian(other.lat / COORDINATE_PRECISION);
|
||||
const float lat2 = DegreeToRadian(lat / COORDINATE_PRECISION);
|
||||
coordinate_calculation::deg_to_rad(lon / COORDINATE_PRECISION - other.lon / COORDINATE_PRECISION);
|
||||
const float lat1 = coordinate_calculation::deg_to_rad(other.lat / COORDINATE_PRECISION);
|
||||
const float lat2 = coordinate_calculation::deg_to_rad(lat / COORDINATE_PRECISION);
|
||||
const float y_value = std::sin(lon_delta) * std::cos(lat2);
|
||||
const float x_value =
|
||||
std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(lon_delta);
|
||||
float result = RadianToDegree(std::atan2(y_value, x_value));
|
||||
float result = coordinate_calculation::rad_to_deg(std::atan2(y_value, x_value));
|
||||
|
||||
while (result < 0.f)
|
||||
{
|
||||
@ -328,75 +113,3 @@ float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &other) const
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::DegreeToRadian(const float degree)
|
||||
{
|
||||
return degree * (static_cast<float>(M_PI) / 180.f);
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::RadianToDegree(const float radian)
|
||||
{
|
||||
return radian * (180.f * static_cast<float>(M_1_PI));
|
||||
}
|
||||
|
||||
// This distance computation does integer arithmetic only and is a lot faster than
|
||||
// the other distance function which are numerically correct('ish).
|
||||
// It preserves some order among the elements that make it useful for certain purposes
|
||||
int FixedPointCoordinate::OrderedPerpendicularDistanceApproximation(
|
||||
const FixedPointCoordinate &input_point,
|
||||
const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target)
|
||||
{
|
||||
// initialize values
|
||||
const float x = static_cast<float>(mercator::lat2y(input_point.lat / COORDINATE_PRECISION));
|
||||
const float y = input_point.lon / COORDINATE_PRECISION;
|
||||
const float a = static_cast<float>(mercator::lat2y(segment_source.lat / COORDINATE_PRECISION));
|
||||
const float b = segment_source.lon / COORDINATE_PRECISION;
|
||||
const float c = static_cast<float>(mercator::lat2y(segment_target.lat / COORDINATE_PRECISION));
|
||||
const float d = segment_target.lon / COORDINATE_PRECISION;
|
||||
|
||||
float p, q;
|
||||
if (a == c)
|
||||
{
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
const float m = (d - b) / (c - a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
|
||||
q = b + m * (p - a);
|
||||
}
|
||||
|
||||
const float nY = (d * p - c * q) / (a * d - b * c);
|
||||
float ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need
|
||||
// not calculate the explicit values of m an n as we
|
||||
// are just interested in the ratio
|
||||
if (std::isnan(ratio))
|
||||
{
|
||||
ratio = (segment_target == input_point) ? 1.f : 0.f;
|
||||
}
|
||||
|
||||
// compute target quasi-location
|
||||
int dx, dy;
|
||||
if (ratio < 0.f)
|
||||
{
|
||||
dx = input_point.lon - segment_source.lon;
|
||||
dy = input_point.lat - segment_source.lat;
|
||||
}
|
||||
else if (ratio > 1.f)
|
||||
{
|
||||
dx = input_point.lon - segment_target.lon;
|
||||
dy = input_point.lat - segment_target.lat;
|
||||
}
|
||||
else
|
||||
{
|
||||
// point lies in between
|
||||
dx = input_point.lon - static_cast<int>(q * COORDINATE_PRECISION);
|
||||
dy = input_point.lat - static_cast<int>(mercator::y2lat(p) * COORDINATE_PRECISION);
|
||||
}
|
||||
|
||||
// return an approximation in the plane
|
||||
return static_cast<int>(sqrt(dx * dx + dy * dy));
|
||||
}
|
||||
|
422
data_structures/coordinate_calculation.cpp
Normal file
422
data_structures/coordinate_calculation.cpp
Normal file
@ -0,0 +1,422 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
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.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
|
||||
|
||||
*/
|
||||
|
||||
#include "coordinate_calculation.hpp"
|
||||
|
||||
#include "../Util/mercator.hpp"
|
||||
#include "../Util/string_util.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr static const float RAD = 0.017453292519943295769236907684886;
|
||||
constexpr static const float earth_radius = 6372797.560856f;
|
||||
}
|
||||
|
||||
double coordinate_calculation::ApproximateDistance(const int lat1,
|
||||
const int lon1,
|
||||
const int lat2,
|
||||
const int lon2)
|
||||
{
|
||||
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||
double lt1 = lat1 / COORDINATE_PRECISION;
|
||||
double ln1 = lon1 / COORDINATE_PRECISION;
|
||||
double lt2 = lat2 / COORDINATE_PRECISION;
|
||||
double ln2 = lon2 / COORDINATE_PRECISION;
|
||||
double dlat1 = lt1 * (RAD);
|
||||
|
||||
double dlong1 = ln1 * (RAD);
|
||||
double dlat2 = lt2 * (RAD);
|
||||
double dlong2 = ln2 * (RAD);
|
||||
|
||||
double dLong = dlong1 - dlong2;
|
||||
double dLat = dlat1 - dlat2;
|
||||
|
||||
double aHarv = pow(sin(dLat / 2.0), 2.0) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2.), 2);
|
||||
double cHarv = 2. * atan2(sqrt(aHarv), sqrt(1.0 - aHarv));
|
||||
// earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
|
||||
// The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
|
||||
return earth_radius * cHarv;
|
||||
}
|
||||
|
||||
double coordinate_calculation::ApproximateDistance(const FixedPointCoordinate &coordinate_1,
|
||||
const FixedPointCoordinate &coordinate_2)
|
||||
{
|
||||
return ApproximateDistance(
|
||||
coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
|
||||
}
|
||||
|
||||
float coordinate_calculation::approx_euclidean_distance(const FixedPointCoordinate &coordinate_1,
|
||||
const FixedPointCoordinate &coordinate_2)
|
||||
{
|
||||
return approx_euclidean_distance(
|
||||
coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
|
||||
}
|
||||
|
||||
float coordinate_calculation::approx_euclidean_distance(const int lat1,
|
||||
const int lon1,
|
||||
const int lat2,
|
||||
const int lon2)
|
||||
{
|
||||
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||
|
||||
const float float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD;
|
||||
const float float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD;
|
||||
const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD;
|
||||
const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD;
|
||||
|
||||
const float x_value = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.f);
|
||||
const float y_value = float_lat2 - float_lat1;
|
||||
return sqrt(x_value * x_value + y_value * y_value) * earth_radius;
|
||||
}
|
||||
|
||||
float
|
||||
coordinate_calculation::ComputePerpendicularDistance(const FixedPointCoordinate &source_coordinate,
|
||||
const FixedPointCoordinate &target_coordinate,
|
||||
const FixedPointCoordinate &query_location)
|
||||
{
|
||||
float ratio;
|
||||
FixedPointCoordinate nearest_location;
|
||||
|
||||
return ComputePerpendicularDistance(source_coordinate,
|
||||
target_coordinate,
|
||||
query_location,
|
||||
nearest_location,
|
||||
ratio);
|
||||
}
|
||||
|
||||
float coordinate_calculation::ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
float &ratio)
|
||||
{
|
||||
BOOST_ASSERT(query_location.is_valid());
|
||||
|
||||
// initialize values
|
||||
const double x = mercator::lat2y(query_location.lat / COORDINATE_PRECISION);
|
||||
const double y = query_location.lon / COORDINATE_PRECISION;
|
||||
const double a = mercator::lat2y(segment_source.lat / COORDINATE_PRECISION);
|
||||
const double b = segment_source.lon / COORDINATE_PRECISION;
|
||||
const double c = mercator::lat2y(segment_target.lat / COORDINATE_PRECISION);
|
||||
const double d = segment_target.lon / COORDINATE_PRECISION;
|
||||
double p, q /*,mX*/, nY;
|
||||
if (std::abs(a - c) > std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
const double m = (d - b) / (c - a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
|
||||
q = b + m * (p - a);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
nY = (d * p - c * q) / (a * d - b * c);
|
||||
|
||||
// discretize the result to coordinate precision. it's a hack!
|
||||
if (std::abs(nY) < (1.f / COORDINATE_PRECISION))
|
||||
{
|
||||
nY = 0.f;
|
||||
}
|
||||
|
||||
// compute ratio
|
||||
ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need
|
||||
// not calculate the explicit values of m an n as we
|
||||
// are just interested in the ratio
|
||||
if (std::isnan(ratio))
|
||||
{
|
||||
ratio = (segment_target == query_location ? 1.f : 0.f);
|
||||
}
|
||||
else if (std::abs(ratio) <= std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
ratio = 0.f;
|
||||
}
|
||||
else if (std::abs(ratio - 1.f) <= std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
ratio = 1.f;
|
||||
}
|
||||
|
||||
// compute nearest location
|
||||
BOOST_ASSERT(!std::isnan(ratio));
|
||||
if (ratio <= 0.f)
|
||||
{
|
||||
nearest_location = segment_source;
|
||||
}
|
||||
else if (ratio >= 1.f)
|
||||
{
|
||||
nearest_location = segment_target;
|
||||
}
|
||||
else
|
||||
{
|
||||
// point lies in between
|
||||
nearest_location.lat = static_cast<int>(mercator::y2lat(p) * COORDINATE_PRECISION);
|
||||
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
|
||||
}
|
||||
BOOST_ASSERT(nearest_location.is_valid());
|
||||
|
||||
const float approximate_distance =
|
||||
coordinate_calculation::approx_euclidean_distance(query_location, nearest_location);
|
||||
BOOST_ASSERT(0. <= approximate_distance);
|
||||
return approximate_distance;
|
||||
}
|
||||
|
||||
float
|
||||
coordinate_calculation::perpendicular_distance_from_projected_coordinate(
|
||||
const FixedPointCoordinate &source_coordinate,
|
||||
const FixedPointCoordinate &target_coordinate,
|
||||
const FixedPointCoordinate &query_location,
|
||||
const std::pair<double, double> &projected_coordinate)
|
||||
{
|
||||
float ratio;
|
||||
FixedPointCoordinate nearest_location;
|
||||
|
||||
return perpendicular_distance_from_projected_coordinate(source_coordinate,
|
||||
target_coordinate,
|
||||
query_location,
|
||||
projected_coordinate,
|
||||
nearest_location,
|
||||
ratio);
|
||||
}
|
||||
|
||||
float coordinate_calculation::perpendicular_distance_from_projected_coordinate(
|
||||
const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
const std::pair<double, double> &projected_coordinate,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
float &ratio)
|
||||
{
|
||||
BOOST_ASSERT(query_location.is_valid());
|
||||
|
||||
// initialize values
|
||||
const double x = projected_coordinate.first;
|
||||
const double y = projected_coordinate.second;
|
||||
const double a = mercator::lat2y(segment_source.lat / COORDINATE_PRECISION);
|
||||
const double b = segment_source.lon / COORDINATE_PRECISION;
|
||||
const double c = mercator::lat2y(segment_target.lat / COORDINATE_PRECISION);
|
||||
const double d = segment_target.lon / COORDINATE_PRECISION;
|
||||
double p, q /*,mX*/, nY;
|
||||
if (std::abs(a - c) > std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
const double m = (d - b) / (c - a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
|
||||
q = b + m * (p - a);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
nY = (d * p - c * q) / (a * d - b * c);
|
||||
|
||||
// discretize the result to coordinate precision. it's a hack!
|
||||
if (std::abs(nY) < (1.f / COORDINATE_PRECISION))
|
||||
{
|
||||
nY = 0.f;
|
||||
}
|
||||
|
||||
// compute ratio
|
||||
ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need
|
||||
// not calculate the explicit values of m an n as we
|
||||
// are just interested in the ratio
|
||||
if (std::isnan(ratio))
|
||||
{
|
||||
ratio = (segment_target == query_location ? 1.f : 0.f);
|
||||
}
|
||||
else if (std::abs(ratio) <= std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
ratio = 0.f;
|
||||
}
|
||||
else if (std::abs(ratio - 1.f) <= std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
ratio = 1.f;
|
||||
}
|
||||
|
||||
// compute nearest location
|
||||
BOOST_ASSERT(!std::isnan(ratio));
|
||||
if (ratio <= 0.f)
|
||||
{
|
||||
nearest_location = segment_source;
|
||||
}
|
||||
else if (ratio >= 1.f)
|
||||
{
|
||||
nearest_location = segment_target;
|
||||
}
|
||||
else
|
||||
{
|
||||
// point lies in between
|
||||
nearest_location.lat = static_cast<int>(mercator::y2lat(p) * COORDINATE_PRECISION);
|
||||
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
|
||||
}
|
||||
BOOST_ASSERT(nearest_location.is_valid());
|
||||
|
||||
const float approximate_distance =
|
||||
coordinate_calculation::approx_euclidean_distance(query_location, nearest_location);
|
||||
BOOST_ASSERT(0. <= approximate_distance);
|
||||
return approximate_distance;
|
||||
}
|
||||
|
||||
void coordinate_calculation::lat_or_lon_to_string(const int value, std::string &output)
|
||||
{
|
||||
char buffer[12];
|
||||
buffer[11] = 0; // zero termination
|
||||
output = printInt<11, 6>(buffer, value);
|
||||
}
|
||||
|
||||
void coordinate_calculation::convertInternalCoordinateToString(const FixedPointCoordinate &coord,
|
||||
std::string &output)
|
||||
{
|
||||
std::string tmp;
|
||||
tmp.reserve(23);
|
||||
lat_or_lon_to_string(coord.lon, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
lat_or_lon_to_string(coord.lat, tmp);
|
||||
output += tmp;
|
||||
}
|
||||
|
||||
void
|
||||
coordinate_calculation::convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord,
|
||||
std::string &output)
|
||||
{
|
||||
std::string tmp;
|
||||
tmp.reserve(23);
|
||||
lat_or_lon_to_string(coord.lat, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
lat_or_lon_to_string(coord.lon, tmp);
|
||||
output += tmp;
|
||||
}
|
||||
|
||||
float coordinate_calculation::GetBearing(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate)
|
||||
{
|
||||
const float lon_diff =
|
||||
second_coordinate.lon / COORDINATE_PRECISION - first_coordinate.lon / COORDINATE_PRECISION;
|
||||
const float lon_delta = deg_to_rad(lon_diff);
|
||||
const float lat1 = deg_to_rad(first_coordinate.lat / COORDINATE_PRECISION);
|
||||
const float lat2 = deg_to_rad(second_coordinate.lat / COORDINATE_PRECISION);
|
||||
const float y = sin(lon_delta) * cos(lat2);
|
||||
const float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon_delta);
|
||||
float result = rad_to_deg(std::atan2(y, x));
|
||||
while (result < 0.f)
|
||||
{
|
||||
result += 360.f;
|
||||
}
|
||||
|
||||
while (result >= 360.f)
|
||||
{
|
||||
result -= 360.f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float coordinate_calculation::deg_to_rad(const float degree)
|
||||
{
|
||||
return degree * (static_cast<float>(M_PI) / 180.f);
|
||||
}
|
||||
|
||||
float coordinate_calculation::rad_to_deg(const float radian)
|
||||
{
|
||||
return radian * (180.f * static_cast<float>(M_1_PI));
|
||||
}
|
||||
|
||||
// This distance computation does integer arithmetic only and is a lot faster than
|
||||
// the other distance function which are numerically correct('ish).
|
||||
// It preserves some order among the elements that make it useful for certain purposes
|
||||
int coordinate_calculation::OrderedPerpendicularDistanceApproximation(
|
||||
const FixedPointCoordinate &input_point,
|
||||
const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target)
|
||||
{
|
||||
// initialize values
|
||||
const float x = static_cast<float>(mercator::lat2y(input_point.lat / COORDINATE_PRECISION));
|
||||
const float y = input_point.lon / COORDINATE_PRECISION;
|
||||
const float a = static_cast<float>(mercator::lat2y(segment_source.lat / COORDINATE_PRECISION));
|
||||
const float b = segment_source.lon / COORDINATE_PRECISION;
|
||||
const float c = static_cast<float>(mercator::lat2y(segment_target.lat / COORDINATE_PRECISION));
|
||||
const float d = segment_target.lon / COORDINATE_PRECISION;
|
||||
|
||||
float p, q;
|
||||
if (a == c)
|
||||
{
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
const float m = (d - b) / (c - a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
|
||||
q = b + m * (p - a);
|
||||
}
|
||||
|
||||
const float nY = (d * p - c * q) / (a * d - b * c);
|
||||
float ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need
|
||||
// not calculate the explicit values of m an n as we
|
||||
// are just interested in the ratio
|
||||
if (std::isnan(ratio))
|
||||
{
|
||||
ratio = (segment_target == input_point) ? 1.f : 0.f;
|
||||
}
|
||||
|
||||
// compute target quasi-location
|
||||
int dx, dy;
|
||||
if (ratio < 0.f)
|
||||
{
|
||||
dx = input_point.lon - segment_source.lon;
|
||||
dy = input_point.lat - segment_source.lat;
|
||||
}
|
||||
else if (ratio > 1.f)
|
||||
{
|
||||
dx = input_point.lon - segment_target.lon;
|
||||
dy = input_point.lat - segment_target.lat;
|
||||
}
|
||||
else
|
||||
{
|
||||
// point lies in between
|
||||
dx = input_point.lon - static_cast<int>(q * COORDINATE_PRECISION);
|
||||
dy = input_point.lat - static_cast<int>(mercator::y2lat(p) * COORDINATE_PRECISION);
|
||||
}
|
||||
|
||||
// return an approximation in the plane
|
||||
return static_cast<int>(sqrt(dx * dx + dy * dy));
|
||||
}
|
97
data_structures/coordinate_calculation.hpp
Normal file
97
data_structures/coordinate_calculation.hpp
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
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.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef COORDINATE_CALCULATION
|
||||
#define COORDINATE_CALCULATION
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <iosfwd> //for std::ostream
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
struct coordinate_calculation
|
||||
{
|
||||
static double
|
||||
ApproximateDistance(const int lat1, const int lon1, const int lat2, const int lon2);
|
||||
|
||||
static double ApproximateDistance(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate);
|
||||
|
||||
static float approx_euclidean_distance(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate);
|
||||
|
||||
static float
|
||||
approx_euclidean_distance(const int lat1, const int lon1, const int lat2, const int lon2);
|
||||
|
||||
static float ApproximateSquaredEuclideanDistance(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate);
|
||||
|
||||
static void lat_or_lon_to_string(const int value, std::string &output);
|
||||
|
||||
static void convertInternalCoordinateToString(const FixedPointCoordinate &coordinate,
|
||||
std::string &output);
|
||||
|
||||
static void convertInternalReversedCoordinateToString(const FixedPointCoordinate &coordinate,
|
||||
std::string &output);
|
||||
|
||||
static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location);
|
||||
|
||||
static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
float &ratio);
|
||||
|
||||
static float perpendicular_distance_from_projected_coordinate(
|
||||
const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
const std::pair<double, double> &projected_coordinate);
|
||||
|
||||
static float perpendicular_distance_from_projected_coordinate(
|
||||
const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
const std::pair<double, double> &projected_coordinate,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
float &ratio);
|
||||
|
||||
static int
|
||||
OrderedPerpendicularDistanceApproximation(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location);
|
||||
|
||||
static float GetBearing(const FixedPointCoordinate &A, const FixedPointCoordinate &B);
|
||||
|
||||
static float deg_to_rad(const float degree);
|
||||
static float rad_to_deg(const float radian);
|
||||
};
|
||||
|
||||
#endif //COORDINATE_CALCULATION
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef RECTANGLE_HPP
|
||||
#define RECTANGLE_HPP
|
||||
|
||||
#include "coordinate_calculation.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
@ -115,28 +117,28 @@ struct RectangleInt2D
|
||||
switch (d)
|
||||
{
|
||||
case NORTH:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, location.lon));
|
||||
min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(max_lat, location.lon));
|
||||
break;
|
||||
case SOUTH:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, location.lon));
|
||||
min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(min_lat, location.lon));
|
||||
break;
|
||||
case WEST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, min_lon));
|
||||
min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(location.lat, min_lon));
|
||||
break;
|
||||
case EAST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, max_lon));
|
||||
min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(location.lat, max_lon));
|
||||
break;
|
||||
case NORTH_EAST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, max_lon));
|
||||
min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(max_lat, max_lon));
|
||||
break;
|
||||
case NORTH_WEST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, min_lon));
|
||||
min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(max_lat, min_lon));
|
||||
break;
|
||||
case SOUTH_EAST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, max_lon));
|
||||
min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(min_lat, max_lon));
|
||||
break;
|
||||
case SOUTH_WEST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, min_lon));
|
||||
min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(min_lat, min_lon));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -159,24 +161,24 @@ struct RectangleInt2D
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right)));
|
||||
coordinate_calculation::approx_euclidean_distance(location, upper_left),
|
||||
coordinate_calculation::approx_euclidean_distance(location, upper_right)));
|
||||
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right)));
|
||||
coordinate_calculation::approx_euclidean_distance(location, upper_right),
|
||||
coordinate_calculation::approx_euclidean_distance(location, lower_right)));
|
||||
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left)));
|
||||
std::max(coordinate_calculation::approx_euclidean_distance(location, lower_right),
|
||||
coordinate_calculation::approx_euclidean_distance(location, lower_left)));
|
||||
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left)));
|
||||
std::max(coordinate_calculation::approx_euclidean_distance(location, lower_left),
|
||||
coordinate_calculation::approx_euclidean_distance(location, upper_left)));
|
||||
return min_max_dist;
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "rectangle.hpp"
|
||||
#include "shared_memory_factory.hpp"
|
||||
#include "shared_memory_vector_wrapper.hpp"
|
||||
#include "upper_bound.hpp"
|
||||
|
||||
#include "../Util/floating_point.hpp"
|
||||
#include "../Util/integer_range.hpp"
|
||||
@ -176,28 +177,28 @@ class StaticRTree
|
||||
switch (d)
|
||||
{
|
||||
case NORTH:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, location.lon));
|
||||
min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(max_lat, location.lon));
|
||||
break;
|
||||
case SOUTH:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, location.lon));
|
||||
min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(min_lat, location.lon));
|
||||
break;
|
||||
case WEST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, min_lon));
|
||||
min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(location.lat, min_lon));
|
||||
break;
|
||||
case EAST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, max_lon));
|
||||
min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(location.lat, max_lon));
|
||||
break;
|
||||
case NORTH_EAST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, max_lon));
|
||||
min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(max_lat, max_lon));
|
||||
break;
|
||||
case NORTH_WEST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, min_lon));
|
||||
min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(max_lat, min_lon));
|
||||
break;
|
||||
case SOUTH_EAST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, max_lon));
|
||||
min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(min_lat, max_lon));
|
||||
break;
|
||||
case SOUTH_WEST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, min_lon));
|
||||
min_dist = coordinate_calculation::approx_euclidean_distance(location, FixedPointCoordinate(min_lat, min_lon));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -220,24 +221,24 @@ class StaticRTree
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right)));
|
||||
coordinate_calculation::approx_euclidean_distance(location, upper_left),
|
||||
coordinate_calculation::approx_euclidean_distance(location, upper_right)));
|
||||
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right)));
|
||||
coordinate_calculation::approx_euclidean_distance(location, upper_right),
|
||||
coordinate_calculation::approx_euclidean_distance(location, lower_right)));
|
||||
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left)));
|
||||
std::max(coordinate_calculation::approx_euclidean_distance(location, lower_right),
|
||||
coordinate_calculation::approx_euclidean_distance(location, lower_left)));
|
||||
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left)));
|
||||
std::max(coordinate_calculation::approx_euclidean_distance(location, lower_left),
|
||||
coordinate_calculation::approx_euclidean_distance(location, upper_left)));
|
||||
return min_max_dist;
|
||||
}
|
||||
|
||||
@ -606,7 +607,7 @@ class StaticRTree
|
||||
}
|
||||
|
||||
float current_minimum_distance =
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
coordinate_calculation::approx_euclidean_distance(
|
||||
input_coordinate.lat,
|
||||
input_coordinate.lon,
|
||||
m_coordinate_list->at(current_edge.u).lat,
|
||||
@ -619,7 +620,7 @@ class StaticRTree
|
||||
}
|
||||
|
||||
current_minimum_distance =
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
coordinate_calculation::approx_euclidean_distance(
|
||||
input_coordinate.lat,
|
||||
input_coordinate.lon,
|
||||
m_coordinate_list->at(current_edge.v).lat,
|
||||
@ -661,6 +662,15 @@ class StaticRTree
|
||||
unsigned number_of_elements_from_big_cc = 0;
|
||||
unsigned number_of_elements_from_tiny_cc = 0;
|
||||
|
||||
unsigned pruned_elements = 0;
|
||||
|
||||
std::pair<double, double> projected_coordinate =
|
||||
{ mercator::lat2y(input_coordinate.lat / COORDINATE_PRECISION),
|
||||
input_coordinate.lon / COORDINATE_PRECISION };
|
||||
|
||||
// upper bound pruning technique
|
||||
upper_bound<float> pruning_bound(max_number_of_phantom_nodes);
|
||||
|
||||
// initialize queue with root element
|
||||
std::priority_queue<IncrementalQueryCandidate> traversal_queue;
|
||||
traversal_queue.emplace(0.f, m_search_tree[0]);
|
||||
@ -683,15 +693,22 @@ class StaticRTree
|
||||
{
|
||||
const auto ¤t_edge = current_leaf_node.objects[i];
|
||||
const float current_perpendicular_distance =
|
||||
FixedPointCoordinate::ComputePerpendicularDistance(
|
||||
coordinate_calculation::perpendicular_distance_from_projected_coordinate(
|
||||
m_coordinate_list->at(current_edge.u),
|
||||
m_coordinate_list->at(current_edge.v),
|
||||
input_coordinate);
|
||||
input_coordinate,
|
||||
projected_coordinate);
|
||||
// distance must be non-negative
|
||||
BOOST_ASSERT(0.f <= current_perpendicular_distance);
|
||||
|
||||
// put element in queue
|
||||
if (pruning_bound.get() >= current_perpendicular_distance ||
|
||||
current_edge.is_in_tiny_cc())
|
||||
{
|
||||
pruning_bound.insert(current_perpendicular_distance);
|
||||
traversal_queue.emplace(current_perpendicular_distance, current_edge);
|
||||
} else {
|
||||
++pruned_elements;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -727,10 +744,11 @@ class StaticRTree
|
||||
float current_ratio = 0.f;
|
||||
FixedPointCoordinate foot_point_coordinate_on_segment;
|
||||
// const float current_perpendicular_distance =
|
||||
FixedPointCoordinate::ComputePerpendicularDistance(
|
||||
coordinate_calculation::perpendicular_distance_from_projected_coordinate(
|
||||
m_coordinate_list->at(current_segment.u),
|
||||
m_coordinate_list->at(current_segment.v),
|
||||
input_coordinate,
|
||||
projected_coordinate,
|
||||
foot_point_coordinate_on_segment,
|
||||
current_ratio);
|
||||
|
||||
@ -766,13 +784,6 @@ class StaticRTree
|
||||
{ // found an element in a big component
|
||||
++number_of_elements_from_big_cc;
|
||||
}
|
||||
|
||||
// SimpleLogger().Write() << "result_phantom_node_vector.size(): " << result_phantom_node_vector.size();
|
||||
// SimpleLogger().Write() << "max_number_of_phantom_nodes: " << max_number_of_phantom_nodes;
|
||||
// SimpleLogger().Write() << "number_of_elements_from_big_cc: " << number_of_elements_from_big_cc;
|
||||
// SimpleLogger().Write() << "number_of_elements_from_tiny_cc: " << number_of_elements_from_tiny_cc;
|
||||
// SimpleLogger().Write() << "inspected_elements: " << inspected_elements;
|
||||
// SimpleLogger().Write() << "max_checked_elements: " << max_checked_elements;
|
||||
}
|
||||
|
||||
// stop the search by flushing the queue
|
||||
@ -782,7 +793,14 @@ class StaticRTree
|
||||
traversal_queue = std::priority_queue<IncrementalQueryCandidate>{};
|
||||
}
|
||||
}
|
||||
// SimpleLogger().Write() << "result_phantom_node_vector.size(): " << result_phantom_node_vector.size();
|
||||
// SimpleLogger().Write() << "max_number_of_phantom_nodes: " << max_number_of_phantom_nodes;
|
||||
// SimpleLogger().Write() << "number_of_elements_from_big_cc: " << number_of_elements_from_big_cc;
|
||||
// SimpleLogger().Write() << "number_of_elements_from_tiny_cc: " << number_of_elements_from_tiny_cc;
|
||||
// SimpleLogger().Write() << "inspected_elements: " << inspected_elements;
|
||||
// SimpleLogger().Write() << "max_checked_elements: " << max_checked_elements;
|
||||
// SimpleLogger().Write() << "pruned_elements: " << pruned_elements;
|
||||
|
||||
return !result_phantom_node_vector.empty();
|
||||
}
|
||||
|
||||
@ -828,7 +846,7 @@ class StaticRTree
|
||||
{
|
||||
const auto ¤t_edge = current_leaf_node.objects[i];
|
||||
const float current_perpendicular_distance =
|
||||
FixedPointCoordinate::ComputePerpendicularDistance(
|
||||
coordinate_calculation::ComputePerpendicularDistance(
|
||||
m_coordinate_list->at(current_edge.u),
|
||||
m_coordinate_list->at(current_edge.v),
|
||||
input_coordinate);
|
||||
@ -885,7 +903,7 @@ class StaticRTree
|
||||
float current_ratio = 0.;
|
||||
FixedPointCoordinate foot_point_coordinate_on_segment;
|
||||
const float current_perpendicular_distance =
|
||||
FixedPointCoordinate::ComputePerpendicularDistance(
|
||||
coordinate_calculation::ComputePerpendicularDistance(
|
||||
m_coordinate_list->at(current_segment.u),
|
||||
m_coordinate_list->at(current_segment.v),
|
||||
input_coordinate,
|
||||
@ -985,7 +1003,7 @@ class StaticRTree
|
||||
float current_ratio = 0.;
|
||||
FixedPointCoordinate nearest;
|
||||
const float current_perpendicular_distance =
|
||||
FixedPointCoordinate::ComputePerpendicularDistance(
|
||||
coordinate_calculation::ComputePerpendicularDistance(
|
||||
m_coordinate_list->at(current_edge.u),
|
||||
m_coordinate_list->at(current_edge.v),
|
||||
input_coordinate,
|
||||
@ -1042,9 +1060,9 @@ class StaticRTree
|
||||
inline void SetForwardAndReverseWeightsOnPhantomNode(const EdgeDataT & nearest_edge,
|
||||
PhantomNode &result_phantom_node) const
|
||||
{
|
||||
const float distance_1 = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
const float distance_1 = coordinate_calculation::approx_euclidean_distance(
|
||||
m_coordinate_list->at(nearest_edge.u), result_phantom_node.location);
|
||||
const float distance_2 = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
const float distance_2 = coordinate_calculation::approx_euclidean_distance(
|
||||
m_coordinate_list->at(nearest_edge.u), m_coordinate_list->at(nearest_edge.v));
|
||||
const float ratio = std::min(1.f, distance_1 / distance_2);
|
||||
|
||||
|
75
data_structures/upper_bound.hpp
Normal file
75
data_structures/upper_bound.hpp
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
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.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef LOWER_BOUND_HPP
|
||||
#define LOWER_BOUND_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <queue>
|
||||
|
||||
// max pq holds k elements
|
||||
// insert if key is smaller than max
|
||||
// if size > k then remove element
|
||||
// get() always yields a bound to the k smallest element in the stream
|
||||
|
||||
template<typename key_type>
|
||||
class upper_bound
|
||||
{
|
||||
public:
|
||||
upper_bound() = delete;
|
||||
upper_bound(std::size_t size) : size(size)
|
||||
{
|
||||
}
|
||||
|
||||
key_type get() const
|
||||
{
|
||||
if (queue.size() < size)
|
||||
{
|
||||
return std::numeric_limits<key_type>::max();
|
||||
}
|
||||
return queue.top();
|
||||
}
|
||||
|
||||
void insert(const key_type key)
|
||||
{
|
||||
if (key < get())
|
||||
{
|
||||
queue.emplace(key);
|
||||
while (queue.size() > size)
|
||||
{
|
||||
queue.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::priority_queue<key_type, std::vector<key_type>, std::less<key_type>> queue;
|
||||
const std::size_t size;
|
||||
};
|
||||
|
||||
#endif // LOWER_BOUND_HPP
|
@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "description_factory.hpp"
|
||||
|
||||
#include "../algorithms/polyline_formatter.hpp"
|
||||
#include "../data_structures/coordinate_calculation.hpp"
|
||||
#include "../data_structures/internal_route_result.hpp"
|
||||
#include "../data_structures/turn_instructions.hpp"
|
||||
#include "../typedefs.h"
|
||||
@ -134,7 +135,7 @@ void DescriptionFactory::Run(const unsigned zoom_level)
|
||||
{
|
||||
// move down names by one, q&d hack
|
||||
path_description[i - 1].name_id = path_description[i].name_id;
|
||||
path_description[i].length = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
path_description[i].length = coordinate_calculation::approx_euclidean_distance(
|
||||
path_description[i - 1].location, path_description[i].location);
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef DESCRIPTOR_BASE_HPP
|
||||
#define DESCRIPTOR_BASE_HPP
|
||||
|
||||
#include "../data_structures/coordinate_calculation.hpp"
|
||||
#include "../data_structures/internal_route_result.hpp"
|
||||
#include "../data_structures/phantom_node.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -49,10 +49,10 @@ template <class DataFacadeT> class GPXDescriptor final : public BaseDescriptor<D
|
||||
|
||||
std::string tmp;
|
||||
|
||||
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lat, tmp);
|
||||
coordinate_calculation::lat_or_lon_to_string(coordinate.lat, tmp);
|
||||
json_lat.values["_lat"] = tmp;
|
||||
|
||||
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lon, tmp);
|
||||
coordinate_calculation::lat_or_lon_to_string(coordinate.lon, tmp);
|
||||
json_lon.values["_lon"] = tmp;
|
||||
|
||||
json_row.values.push_back(json_lat);
|
||||
|
@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "extraction_containers.hpp"
|
||||
#include "extraction_way.hpp"
|
||||
|
||||
#include "../data_structures/coordinate_calculation.hpp"
|
||||
#include "../data_structures/node_id.hpp"
|
||||
#include "../data_structures/range_table.hpp"
|
||||
|
||||
@ -327,7 +328,7 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||
edge_iterator->target_coordinate.lat = node_iterator->lat;
|
||||
edge_iterator->target_coordinate.lon = node_iterator->lon;
|
||||
|
||||
const double distance = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
const double distance = coordinate_calculation::approx_euclidean_distance(
|
||||
edge_iterator->source_coordinate.lat,
|
||||
edge_iterator->source_coordinate.lon,
|
||||
node_iterator->lat,
|
||||
|
@ -1,5 +1,34 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
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.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
|
||||
|
||||
*/
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include "../../data_structures/coordinate_calculation.hpp"
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <cmath>
|
||||
@ -11,11 +40,11 @@ BOOST_AUTO_TEST_CASE(regression_test_1347)
|
||||
FixedPointCoordinate v(10.001 * COORDINATE_PRECISION, -100.002 * COORDINATE_PRECISION);
|
||||
FixedPointCoordinate q(10.002 * COORDINATE_PRECISION, -100.001 * COORDINATE_PRECISION);
|
||||
|
||||
float d1 = FixedPointCoordinate::ComputePerpendicularDistance(u, v, q);
|
||||
float d1 = coordinate_calculation::ComputePerpendicularDistance(u, v, q);
|
||||
|
||||
float ratio;
|
||||
FixedPointCoordinate nearest_location;
|
||||
float d2 = FixedPointCoordinate::ComputePerpendicularDistance(u, v, q, nearest_location, ratio);
|
||||
float d2 = coordinate_calculation::ComputePerpendicularDistance(u, v, q, nearest_location, ratio);
|
||||
|
||||
BOOST_CHECK_LE(std::abs(d1 - d2), 0.01f);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -25,6 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "../../data_structures/coordinate_calculation.hpp"
|
||||
#include "../../data_structures/static_rtree.hpp"
|
||||
#include "../../data_structures/query_node.hpp"
|
||||
#include "../../data_structures/edge_based_node.hpp"
|
||||
@ -77,7 +78,7 @@ class LinearSearchNN
|
||||
{
|
||||
const FixedPointCoordinate &start = coords->at(e.u);
|
||||
const FixedPointCoordinate &end = coords->at(e.v);
|
||||
float distance = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
float distance = coordinate_calculation::approx_euclidean_distance(
|
||||
input_coordinate.lat, input_coordinate.lon, start.lat, start.lon);
|
||||
if (distance < min_dist)
|
||||
{
|
||||
@ -85,7 +86,7 @@ class LinearSearchNN
|
||||
min_dist = distance;
|
||||
}
|
||||
|
||||
distance = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
distance = coordinate_calculation::approx_euclidean_distance(
|
||||
input_coordinate.lat, input_coordinate.lon, end.lat, end.lon);
|
||||
if (distance < min_dist)
|
||||
{
|
||||
@ -112,7 +113,7 @@ class LinearSearchNN
|
||||
float current_ratio = 0.;
|
||||
FixedPointCoordinate nearest;
|
||||
const float current_perpendicular_distance =
|
||||
FixedPointCoordinate::ComputePerpendicularDistance(
|
||||
coordinate_calculation::ComputePerpendicularDistance(
|
||||
coords->at(e.u), coords->at(e.v), input_coordinate, nearest, current_ratio);
|
||||
|
||||
if ((current_perpendicular_distance < min_dist) &&
|
||||
@ -148,9 +149,9 @@ class LinearSearchNN
|
||||
result_phantom_node.location.lat = input_coordinate.lat;
|
||||
}
|
||||
|
||||
const float distance_1 = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
const float distance_1 = coordinate_calculation::approx_euclidean_distance(
|
||||
coords->at(nearest_edge.u), result_phantom_node.location);
|
||||
const float distance_2 = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
const float distance_2 = coordinate_calculation::approx_euclidean_distance(
|
||||
coords->at(nearest_edge.u), coords->at(nearest_edge.v));
|
||||
const float ratio = std::min(1.f, distance_1 / distance_2);
|
||||
|
||||
@ -285,10 +286,10 @@ void simple_verify_rtree(RTreeT &rtree,
|
||||
bool found_u = rtree.LocateClosestEndPointForCoordinate(pu, result_u, 1);
|
||||
bool found_v = rtree.LocateClosestEndPointForCoordinate(pv, result_v, 1);
|
||||
BOOST_CHECK(found_u && found_v);
|
||||
float dist_u = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
float dist_u = coordinate_calculation::approx_euclidean_distance(
|
||||
result_u.lat, result_u.lon, pu.lat, pu.lon);
|
||||
BOOST_CHECK_LE(dist_u, std::numeric_limits<float>::epsilon());
|
||||
float dist_v = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
float dist_v = coordinate_calculation::approx_euclidean_distance(
|
||||
result_v.lat, result_v.lon, pv.lat, pv.lon);
|
||||
BOOST_CHECK_LE(dist_v, std::numeric_limits<float>::epsilon());
|
||||
}
|
||||
@ -449,30 +450,30 @@ void TestRectangle(double width, double height, double center_lat, double center
|
||||
|
||||
/* Distance to line segments of rectangle */
|
||||
BOOST_CHECK_EQUAL(rect.GetMinDist(north),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
coordinate_calculation::approx_euclidean_distance(
|
||||
north, FixedPointCoordinate(rect.max_lat, north.lon)));
|
||||
BOOST_CHECK_EQUAL(rect.GetMinDist(south),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
coordinate_calculation::approx_euclidean_distance(
|
||||
south, FixedPointCoordinate(rect.min_lat, south.lon)));
|
||||
BOOST_CHECK_EQUAL(rect.GetMinDist(west),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
coordinate_calculation::approx_euclidean_distance(
|
||||
west, FixedPointCoordinate(west.lat, rect.min_lon)));
|
||||
BOOST_CHECK_EQUAL(rect.GetMinDist(east),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
coordinate_calculation::approx_euclidean_distance(
|
||||
east, FixedPointCoordinate(east.lat, rect.max_lon)));
|
||||
|
||||
/* Distance to corner points */
|
||||
BOOST_CHECK_EQUAL(rect.GetMinDist(north_east),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
coordinate_calculation::approx_euclidean_distance(
|
||||
north_east, FixedPointCoordinate(rect.max_lat, rect.max_lon)));
|
||||
BOOST_CHECK_EQUAL(rect.GetMinDist(north_west),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
coordinate_calculation::approx_euclidean_distance(
|
||||
north_west, FixedPointCoordinate(rect.max_lat, rect.min_lon)));
|
||||
BOOST_CHECK_EQUAL(rect.GetMinDist(south_east),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
coordinate_calculation::approx_euclidean_distance(
|
||||
south_east, FixedPointCoordinate(rect.min_lat, rect.max_lon)));
|
||||
BOOST_CHECK_EQUAL(rect.GetMinDist(south_west),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
coordinate_calculation::approx_euclidean_distance(
|
||||
south_west, FixedPointCoordinate(rect.min_lat, rect.min_lon)));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user