Fix distance calculation consistency. (#6315)
Consolidate great circle distance calculations to use cheap ruler library.
This commit is contained in:
committed by
GitHub
parent
8f0cd5cf7b
commit
aadc088084
@@ -25,7 +25,8 @@ std::pair<short, short> getDepartBearings(const LegGeometry &leg_geometry,
|
||||
const auto turn_coordinate = leg_geometry.locations.front();
|
||||
const auto post_turn_coordinate = *(leg_geometry.locations.begin() + 1);
|
||||
|
||||
if (util::coordinate_calculation::haversineDistance(turn_coordinate, post_turn_coordinate) <= 1)
|
||||
if (util::coordinate_calculation::greatCircleDistance(turn_coordinate, post_turn_coordinate) <=
|
||||
1)
|
||||
{
|
||||
return std::make_pair<short, short>(0, source_node.GetBearing(traversed_in_reverse));
|
||||
}
|
||||
@@ -41,7 +42,8 @@ std::pair<short, short> getArriveBearings(const LegGeometry &leg_geometry,
|
||||
BOOST_ASSERT(leg_geometry.locations.size() >= 2);
|
||||
const auto turn_coordinate = leg_geometry.locations.back();
|
||||
const auto pre_turn_coordinate = *(leg_geometry.locations.end() - 2);
|
||||
if (util::coordinate_calculation::haversineDistance(turn_coordinate, pre_turn_coordinate) <= 1)
|
||||
if (util::coordinate_calculation::greatCircleDistance(turn_coordinate, pre_turn_coordinate) <=
|
||||
1)
|
||||
{
|
||||
return std::make_pair<short, short>(target_node.GetBearing(traversed_in_reverse), 0);
|
||||
}
|
||||
|
||||
@@ -263,7 +263,7 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
|
||||
BOOST_ASSERT(geometry.locations.size() >= steps.size());
|
||||
// Look for distances under 1m
|
||||
const bool zero_length_step = steps.front().distance <= 1 && steps.size() > 2;
|
||||
const bool duplicated_coordinate = util::coordinate_calculation::haversineDistance(
|
||||
const bool duplicated_coordinate = util::coordinate_calculation::greatCircleDistance(
|
||||
geometry.locations[0], geometry.locations[1]) <= 1;
|
||||
if (zero_length_step || duplicated_coordinate)
|
||||
{
|
||||
@@ -406,7 +406,7 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
|
||||
next_to_last_step.mode = new_next_to_last.mode;
|
||||
// the geometry indices of the last step are already correct;
|
||||
}
|
||||
else if (util::coordinate_calculation::haversineDistance(
|
||||
else if (util::coordinate_calculation::greatCircleDistance(
|
||||
geometry.locations[geometry.locations.size() - 2],
|
||||
geometry.locations[geometry.locations.size() - 1]) <= 1)
|
||||
{
|
||||
@@ -463,7 +463,7 @@ std::vector<RouteStep> assignRelativeLocations(std::vector<RouteStep> steps,
|
||||
BOOST_ASSERT(steps.size() >= 2);
|
||||
BOOST_ASSERT(leg_geometry.locations.size() >= 2);
|
||||
const constexpr double MINIMAL_RELATIVE_DISTANCE = 5., MAXIMAL_RELATIVE_DISTANCE = 300.;
|
||||
const auto distance_to_start = util::coordinate_calculation::haversineDistance(
|
||||
const auto distance_to_start = util::coordinate_calculation::greatCircleDistance(
|
||||
source_node.input_location, leg_geometry.locations[0]);
|
||||
const auto initial_modifier =
|
||||
distance_to_start >= MINIMAL_RELATIVE_DISTANCE &&
|
||||
@@ -474,7 +474,7 @@ std::vector<RouteStep> assignRelativeLocations(std::vector<RouteStep> steps,
|
||||
|
||||
steps.front().maneuver.instruction.direction_modifier = initial_modifier;
|
||||
|
||||
const auto distance_from_end = util::coordinate_calculation::haversineDistance(
|
||||
const auto distance_from_end = util::coordinate_calculation::greatCircleDistance(
|
||||
target_node.input_location, leg_geometry.locations.back());
|
||||
const auto final_modifier =
|
||||
distance_from_end >= MINIMAL_RELATIVE_DISTANCE &&
|
||||
|
||||
@@ -116,9 +116,9 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
||||
auto distance_estimate =
|
||||
params.fallback_coordinate_type ==
|
||||
api::TableParameters::FallbackCoordinateType::Input
|
||||
? util::coordinate_calculation::fccApproximateDistance(
|
||||
? util::coordinate_calculation::greatCircleDistance(
|
||||
source.input_location, destination.input_location)
|
||||
: util::coordinate_calculation::fccApproximateDistance(
|
||||
: util::coordinate_calculation::greatCircleDistance(
|
||||
source.location, destination.location);
|
||||
|
||||
result_tables_pair.first[table_index] =
|
||||
|
||||
@@ -464,7 +464,7 @@ void encodeVectorTile(const DataFacadeBase &facade,
|
||||
const auto b = facade.GetCoordinateOfNode(edge.v);
|
||||
// Calculate the length in meters
|
||||
const double length =
|
||||
osrm::util::coordinate_calculation::haversineDistance(a, b);
|
||||
osrm::util::coordinate_calculation::greatCircleDistance(a, b);
|
||||
|
||||
const auto forward_weight_range =
|
||||
facade.GetUncompressedForwardWeights(geometry_id);
|
||||
|
||||
@@ -137,7 +137,7 @@ Parameters parametersFromRequest(const PhantomNodes &phantom_node_pair)
|
||||
{
|
||||
Parameters parameters;
|
||||
|
||||
const auto distance = util::coordinate_calculation::haversineDistance(
|
||||
const auto distance = util::coordinate_calculation::greatCircleDistance(
|
||||
phantom_node_pair.source_phantom.location, phantom_node_pair.target_phantom.location);
|
||||
|
||||
// 10km
|
||||
|
||||
@@ -214,7 +214,7 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const auto ¤t_timestamps_list = candidates_list[t];
|
||||
const auto ¤t_coordinate = trace_coordinates[t];
|
||||
|
||||
const auto haversine_distance = util::coordinate_calculation::haversineDistance(
|
||||
const auto haversine_distance = util::coordinate_calculation::greatCircleDistance(
|
||||
prev_coordinate, current_coordinate);
|
||||
// assumes minumum of 4 m/s
|
||||
const EdgeWeight weight_upper_bound =
|
||||
@@ -424,7 +424,7 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
||||
reconstructed_indices,
|
||||
[&trace_distance, &trace_coordinates](const std::pair<std::size_t, std::size_t> &prev,
|
||||
const std::pair<std::size_t, std::size_t> &curr) {
|
||||
trace_distance += util::coordinate_calculation::haversineDistance(
|
||||
trace_distance += util::coordinate_calculation::greatCircleDistance(
|
||||
trace_coordinates[prev.first], trace_coordinates[curr.first]);
|
||||
});
|
||||
|
||||
|
||||
@@ -434,7 +434,7 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
|
||||
const auto duration = edge_iterator->duration_data(distance);
|
||||
|
||||
const auto accurate_distance =
|
||||
util::coordinate_calculation::fccApproximateDistance(source_coord, target_coord);
|
||||
util::coordinate_calculation::greatCircleDistance(source_coord, target_coord);
|
||||
|
||||
ExtractionSegment segment(source_coord, target_coord, distance, weight, duration);
|
||||
scripting_environment.ProcessSegment(segment);
|
||||
|
||||
@@ -146,12 +146,12 @@ util::Coordinate CoordinateExtractor::ExtractRepresentativeCoordinate(
|
||||
// do the best of what we can.
|
||||
coordinates =
|
||||
TrimCoordinatesToLength(std::move(coordinates), LOOKAHEAD_DISTANCE_WITHOUT_LANES);
|
||||
if (coordinates.size() > 2 && util::coordinate_calculation::haversineDistance(
|
||||
if (coordinates.size() > 2 && util::coordinate_calculation::greatCircleDistance(
|
||||
turn_coordinate, coordinates[1]) < ASSUMED_LANE_WIDTH)
|
||||
{
|
||||
const auto initial_distance =
|
||||
util::coordinate_calculation::haversineDistance(turn_coordinate, coordinates[1]);
|
||||
const auto total_distance = util::coordinate_calculation::haversineDistance(
|
||||
util::coordinate_calculation::greatCircleDistance(turn_coordinate, coordinates[1]);
|
||||
const auto total_distance = util::coordinate_calculation::greatCircleDistance(
|
||||
turn_coordinate, coordinates.back());
|
||||
|
||||
if (initial_distance > ASSUMED_LANE_WIDTH && total_distance > initial_distance)
|
||||
@@ -169,7 +169,7 @@ util::Coordinate CoordinateExtractor::ExtractRepresentativeCoordinate(
|
||||
}
|
||||
|
||||
const auto first_distance =
|
||||
util::coordinate_calculation::haversineDistance(coordinates[0], coordinates[1]);
|
||||
util::coordinate_calculation::greatCircleDistance(coordinates[0], coordinates[1]);
|
||||
|
||||
// the lane count might not always be set. We need to assume a positive number, though. Here we
|
||||
// select the number of lanes to operate on
|
||||
@@ -369,7 +369,7 @@ util::Coordinate CoordinateExtractor::ExtractRepresentativeCoordinate(
|
||||
std::move(coordinates), 3 * skipping_inaccuracies_distance, segment_distances);
|
||||
BOOST_ASSERT(coordinates.size() >= 2);
|
||||
segment_distances.resize(coordinates.size());
|
||||
segment_distances.back() = util::coordinate_calculation::haversineDistance(
|
||||
segment_distances.back() = util::coordinate_calculation::greatCircleDistance(
|
||||
*(coordinates.end() - 2), coordinates.back());
|
||||
const auto vector_head = coordinates.back();
|
||||
coordinates = TrimCoordinatesToLength(
|
||||
@@ -476,7 +476,7 @@ util::Coordinate CoordinateExtractor::ExtractCoordinateAtLength(
|
||||
[distance, &accumulated_distance, last_coordinate = coordinates.front()](
|
||||
const util::Coordinate coordinate) mutable {
|
||||
const double segment_distance =
|
||||
util::coordinate_calculation::haversineDistance(last_coordinate, coordinate);
|
||||
util::coordinate_calculation::greatCircleDistance(last_coordinate, coordinate);
|
||||
const auto result = (accumulated_distance + segment_distance) >= distance;
|
||||
if (!result)
|
||||
{
|
||||
@@ -497,7 +497,7 @@ util::Coordinate CoordinateExtractor::ExtractCoordinateAtLength(
|
||||
const auto interpolation_factor =
|
||||
ComputeInterpolationFactor(distance - accumulated_distance,
|
||||
0,
|
||||
util::coordinate_calculation::haversineDistance(
|
||||
util::coordinate_calculation::greatCircleDistance(
|
||||
*std::prev(coordinate_after), *coordinate_after));
|
||||
|
||||
return util::coordinate_calculation::interpolateLinear(
|
||||
@@ -533,7 +533,7 @@ util::Coordinate CoordinateExtractor::GetCoordinateCloseToTurn(const NodeID from
|
||||
const auto far_enough_away =
|
||||
[start_coordinate, compressedGeometryToCoordinate](
|
||||
const CompressedEdgeContainer::OnewayCompressedEdge &compressed_edge) {
|
||||
return util::coordinate_calculation::haversineDistance(
|
||||
return util::coordinate_calculation::greatCircleDistance(
|
||||
compressedGeometryToCoordinate(compressed_edge), start_coordinate) > 1;
|
||||
};
|
||||
|
||||
@@ -627,7 +627,7 @@ CoordinateExtractor::GetMaxDeviation(std::vector<util::Coordinate>::const_iterat
|
||||
.second;
|
||||
// and calculate the distance between the intermediate coordinate and the coordinate
|
||||
// on the osrm-way
|
||||
return util::coordinate_calculation::haversineDistance(coord_between, coordinate);
|
||||
return util::coordinate_calculation::greatCircleDistance(coord_between, coordinate);
|
||||
};
|
||||
|
||||
// note: we don't accumulate here but rather compute the maximum. The functor passed here is not
|
||||
@@ -671,7 +671,7 @@ bool CoordinateExtractor::IsCurve(const std::vector<util::Coordinate> &coordinat
|
||||
auto coord_between =
|
||||
util::coordinate_calculation::projectPointOnSegment(line_start, line_end, point).second;
|
||||
// and calculate the distance between the intermediate coordinate and the coordinate
|
||||
return util::coordinate_calculation::haversineDistance(coord_between, point);
|
||||
return util::coordinate_calculation::greatCircleDistance(coord_between, point);
|
||||
};
|
||||
|
||||
// a curve needs to be on one side of the coordinate array
|
||||
@@ -899,7 +899,7 @@ CoordinateExtractor::PrepareLengthCache(const std::vector<util::Coordinate> &coo
|
||||
limit,
|
||||
&segment_distances,
|
||||
accumulated_distance = 0.](const util::Coordinate current_coordinate) mutable {
|
||||
const auto distance = util::coordinate_calculation::haversineDistance(
|
||||
const auto distance = util::coordinate_calculation::greatCircleDistance(
|
||||
last_coordinate, current_coordinate);
|
||||
accumulated_distance += distance;
|
||||
last_coordinate = current_coordinate;
|
||||
@@ -924,8 +924,8 @@ CoordinateExtractor::TrimCoordinatesToLength(std::vector<util::Coordinate> coord
|
||||
[&coordinate_index, &distance_to_current_coordinate, &coordinates]() {
|
||||
const auto new_distance =
|
||||
distance_to_current_coordinate +
|
||||
util::coordinate_calculation::haversineDistance(coordinates[coordinate_index - 1],
|
||||
coordinates[coordinate_index]);
|
||||
util::coordinate_calculation::greatCircleDistance(coordinates[coordinate_index - 1],
|
||||
coordinates[coordinate_index]);
|
||||
return new_distance;
|
||||
};
|
||||
|
||||
@@ -941,8 +941,8 @@ CoordinateExtractor::TrimCoordinatesToLength(std::vector<util::Coordinate> coord
|
||||
coordinates.erase(coordinates.begin() + length_cache.size(), coordinates.end());
|
||||
|
||||
const auto distance_between_last_coordinates =
|
||||
util::coordinate_calculation::haversineDistance(*(coordinates.end() - 2),
|
||||
*(coordinates.end() - 1));
|
||||
util::coordinate_calculation::greatCircleDistance(*(coordinates.end() - 2),
|
||||
*(coordinates.end() - 1));
|
||||
|
||||
if (distance_between_last_coordinates > 0)
|
||||
{
|
||||
@@ -991,7 +991,7 @@ CoordinateExtractor::GetCorrectedCoordinate(const util::Coordinate fixpoint,
|
||||
{
|
||||
// if the coordinates are close together, we were not able to look far ahead, so
|
||||
// we can use the end-coordinate
|
||||
if (util::coordinate_calculation::haversineDistance(vector_base, vector_head) <
|
||||
if (util::coordinate_calculation::greatCircleDistance(vector_base, vector_head) <
|
||||
DESIRED_COORDINATE_DIFFERENCE)
|
||||
{
|
||||
return vector_head;
|
||||
@@ -1054,7 +1054,7 @@ CoordinateExtractor::SampleCoordinates(const std::vector<util::Coordinate> &coor
|
||||
if (total_length > max_sample_length)
|
||||
return true;
|
||||
|
||||
const auto distance_between = util::coordinate_calculation::haversineDistance(
|
||||
const auto distance_between = util::coordinate_calculation::greatCircleDistance(
|
||||
previous_coordinate, current_coordinate);
|
||||
|
||||
if (carry_length + distance_between >= rate)
|
||||
@@ -1123,7 +1123,7 @@ CoordinateExtractor::TrimCoordinatesByLengthFront(std::vector<util::Coordinate>
|
||||
for (std::size_t next_index = 1; next_index < coordinates.size(); ++next_index)
|
||||
{
|
||||
const double next_distance =
|
||||
distance_to_index + util::coordinate_calculation::haversineDistance(
|
||||
distance_to_index + util::coordinate_calculation::greatCircleDistance(
|
||||
coordinates[index], coordinates[next_index]);
|
||||
if (next_distance >= desired_length)
|
||||
{
|
||||
|
||||
@@ -237,7 +237,7 @@ getIntersectionOutgoingGeometries(const util::NodeBasedDynamicGraph &graph,
|
||||
util::coordinate_calculation::bearing(geometry[0], representative_coordinate);
|
||||
|
||||
const auto edge_length = util::coordinate_calculation::getLength(
|
||||
geometry.begin(), geometry.end(), util::coordinate_calculation::haversineDistance);
|
||||
geometry.begin(), geometry.end(), util::coordinate_calculation::greatCircleDistance);
|
||||
|
||||
edge_geometries.push_back({outgoing_edge, initial_bearing, perceived_bearing, edge_length});
|
||||
}
|
||||
|
||||
@@ -225,7 +225,7 @@ bool MergableRoadDetector::IsNarrowTriangle(const NodeID intersection_node,
|
||||
left_accumulator,
|
||||
selector);
|
||||
}
|
||||
const auto distance_to_triangle = util::coordinate_calculation::haversineDistance(
|
||||
const auto distance_to_triangle = util::coordinate_calculation::greatCircleDistance(
|
||||
node_coordinates[intersection_node],
|
||||
node_coordinates[node_based_graph.GetTarget(left_accumulator.via_edge_id)]);
|
||||
|
||||
@@ -274,9 +274,10 @@ bool MergableRoadDetector::IsNarrowTriangle(const NodeID intersection_node,
|
||||
// the width we can bridge at the intersection
|
||||
const auto assumed_road_width = (num_lanes(lhs) + num_lanes(rhs)) * ASSUMED_LANE_WIDTH;
|
||||
const constexpr auto MAXIMAL_ALLOWED_TRAFFIC_ISLAND_WIDTH = 10;
|
||||
const auto distance_between_triangle_corners = util::coordinate_calculation::haversineDistance(
|
||||
node_coordinates[node_based_graph.GetTarget(left_accumulator.via_edge_id)],
|
||||
node_coordinates[node_based_graph.GetTarget(right_accumulator.via_edge_id)]);
|
||||
const auto distance_between_triangle_corners =
|
||||
util::coordinate_calculation::greatCircleDistance(
|
||||
node_coordinates[node_based_graph.GetTarget(left_accumulator.via_edge_id)],
|
||||
node_coordinates[node_based_graph.GetTarget(right_accumulator.via_edge_id)]);
|
||||
if (distance_between_triangle_corners >
|
||||
(assumed_road_width + MAXIMAL_ALLOWED_TRAFFIC_ISLAND_WIDTH))
|
||||
return false;
|
||||
@@ -540,7 +541,7 @@ bool MergableRoadDetector::IsTrafficIsland(const NodeID intersection_node,
|
||||
if (!degree_three_connect_in && !degree_three_connect_out)
|
||||
return false;
|
||||
|
||||
const auto distance_between_candidates = util::coordinate_calculation::haversineDistance(
|
||||
const auto distance_between_candidates = util::coordinate_calculation::greatCircleDistance(
|
||||
node_coordinates[intersection_node], node_coordinates[left_candidate]);
|
||||
|
||||
const auto both_split_join = degree_three_connect_in && degree_three_connect_out;
|
||||
|
||||
@@ -50,7 +50,7 @@ void LengthLimitedCoordinateAccumulator::update(const NodeID from_node,
|
||||
const auto length =
|
||||
util::coordinate_calculation::getLength(current_coordinates.begin(),
|
||||
current_coordinates.end(),
|
||||
util::coordinate_calculation::haversineDistance);
|
||||
util::coordinate_calculation::greatCircleDistance);
|
||||
|
||||
// in case we get too many coordinates, we limit them to our desired length
|
||||
if (length + accumulated_length > max_length)
|
||||
|
||||
@@ -183,7 +183,7 @@ TurnInstruction IntersectionHandler::getInstructionForObvious(const std::size_t
|
||||
// duration/weight of the traversal. We can only approximate the distance here
|
||||
// or actually follow the full road. When 2399 lands, we can exchange here for a
|
||||
// precalculated distance value.
|
||||
const auto distance = util::coordinate_calculation::haversineDistance(
|
||||
const auto distance = util::coordinate_calculation::greatCircleDistance(
|
||||
node_coordinates[node_based_graph.GetTarget(via_edge)],
|
||||
node_coordinates[node_based_graph.GetTarget(road.eid)]);
|
||||
|
||||
|
||||
@@ -274,7 +274,7 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const
|
||||
for (const auto &compressed_edge : edge_bucket)
|
||||
{
|
||||
const auto next_coord = node_coordinates[compressed_edge.node_id];
|
||||
length += util::coordinate_calculation::haversineDistance(last_coord, next_coord);
|
||||
length += util::coordinate_calculation::greatCircleDistance(last_coord, next_coord);
|
||||
last_coord = next_coord;
|
||||
}
|
||||
return length;
|
||||
|
||||
@@ -56,7 +56,7 @@ std::unordered_set<EdgeID> findSegregatedNodes(const extractor::NodeBasedGraphFa
|
||||
double length = 0.0;
|
||||
for (size_t i = 1; i < geom.size(); ++i)
|
||||
{
|
||||
length += util::coordinate_calculation::haversineDistance(geom[i - 1], geom[i]);
|
||||
length += util::coordinate_calculation::greatCircleDistance(geom[i - 1], geom[i]);
|
||||
}
|
||||
return length;
|
||||
};
|
||||
|
||||
@@ -452,8 +452,8 @@ Intersection SliproadHandler::operator()(const NodeID /*nid*/,
|
||||
// Only check for curvature and ~90 degree when it makes sense to do so.
|
||||
const constexpr auto MIN_LENGTH = 3.;
|
||||
|
||||
const auto length = haversineDistance(node_coordinates[intersection_node_id],
|
||||
node_coordinates[main_road_intersection->node]);
|
||||
const auto length = greatCircleDistance(node_coordinates[intersection_node_id],
|
||||
node_coordinates[main_road_intersection->node]);
|
||||
|
||||
const double minimal_crossroad_angle_of_intersection = 40.;
|
||||
|
||||
@@ -740,8 +740,8 @@ bool SliproadHandler::isValidSliproadArea(const double max_area,
|
||||
const auto second = node_coordinates[b];
|
||||
const auto third = node_coordinates[c];
|
||||
|
||||
const auto length = haversineDistance(first, second);
|
||||
const auto heigth = haversineDistance(second, third);
|
||||
const auto length = greatCircleDistance(first, second);
|
||||
const auto heigth = greatCircleDistance(second, third);
|
||||
|
||||
const auto area = (length * heigth) / 2.;
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ bool findPreviousIntersection(const NodeID node_v,
|
||||
const auto via_edge_length =
|
||||
util::coordinate_calculation::getLength(coordinates_along_via_edge.begin(),
|
||||
coordinates_along_via_edge.end(),
|
||||
&util::coordinate_calculation::haversineDistance);
|
||||
&util::coordinate_calculation::greatCircleDistance);
|
||||
|
||||
// we check if via-edge is too short. In this case the previous turn cannot influence the turn
|
||||
// at via_edge and the intersection at NODE_W
|
||||
|
||||
@@ -72,12 +72,10 @@ std::uint64_t squaredEuclideanDistance(const Coordinate lhs, const Coordinate rh
|
||||
return result;
|
||||
}
|
||||
|
||||
// Uses method described here:
|
||||
// https://www.gpo.gov/fdsys/pkg/CFR-2005-title47-vol4/pdf/CFR-2005-title47-vol4-sec73-208.pdf
|
||||
// should be within 0.1% or so of Vincenty method (assuming 19 buckets are enough)
|
||||
// Should be more faster and more precise than Haversine
|
||||
double fccApproximateDistance(const Coordinate coordinate_1, const Coordinate coordinate_2)
|
||||
double greatCircleDistance(const Coordinate coordinate_1, const Coordinate coordinate_2)
|
||||
{
|
||||
// Should be within 0.1% or so of Vincenty method (assuming 19 buckets are enough)
|
||||
// Should be more faster and more precise than Haversine
|
||||
const auto lon1 = static_cast<double>(util::toFloating(coordinate_1.lon));
|
||||
const auto lat1 = static_cast<double>(util::toFloating(coordinate_1.lat));
|
||||
const auto lon2 = static_cast<double>(util::toFloating(coordinate_2.lon));
|
||||
@@ -86,56 +84,6 @@ double fccApproximateDistance(const Coordinate coordinate_1, const Coordinate co
|
||||
.distance({lon1, lat1}, {lon2, lat2});
|
||||
}
|
||||
|
||||
double haversineDistance(const Coordinate coordinate_1, const Coordinate coordinate_2)
|
||||
{
|
||||
auto lon1 = static_cast<int>(coordinate_1.lon);
|
||||
auto lat1 = static_cast<int>(coordinate_1.lat);
|
||||
auto lon2 = static_cast<int>(coordinate_2.lon);
|
||||
auto lat2 = static_cast<int>(coordinate_2.lat);
|
||||
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||
const double lt1 = lat1 / COORDINATE_PRECISION;
|
||||
const double ln1 = lon1 / COORDINATE_PRECISION;
|
||||
const double lt2 = lat2 / COORDINATE_PRECISION;
|
||||
const double ln2 = lon2 / COORDINATE_PRECISION;
|
||||
|
||||
const double dlat1 = lt1 * detail::DEGREE_TO_RAD;
|
||||
const double dlong1 = ln1 * detail::DEGREE_TO_RAD;
|
||||
const double dlat2 = lt2 * detail::DEGREE_TO_RAD;
|
||||
const double dlong2 = ln2 * detail::DEGREE_TO_RAD;
|
||||
|
||||
const double dlong = dlong1 - dlong2;
|
||||
const double dlat = dlat1 - dlat2;
|
||||
|
||||
const double aharv = std::pow(std::sin(dlat / 2.0), 2.0) +
|
||||
std::cos(dlat1) * std::cos(dlat2) * std::pow(std::sin(dlong / 2.), 2);
|
||||
const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv));
|
||||
return detail::EARTH_RADIUS * charv;
|
||||
}
|
||||
|
||||
double greatCircleDistance(const Coordinate coordinate_1, const Coordinate coordinate_2)
|
||||
{
|
||||
auto lon1 = static_cast<int>(coordinate_1.lon);
|
||||
auto lat1 = static_cast<int>(coordinate_1.lat);
|
||||
auto lon2 = static_cast<int>(coordinate_2.lon);
|
||||
auto lat2 = static_cast<int>(coordinate_2.lat);
|
||||
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 double float_lat1 = (lat1 / COORDINATE_PRECISION) * detail::DEGREE_TO_RAD;
|
||||
const double float_lon1 = (lon1 / COORDINATE_PRECISION) * detail::DEGREE_TO_RAD;
|
||||
const double float_lat2 = (lat2 / COORDINATE_PRECISION) * detail::DEGREE_TO_RAD;
|
||||
const double float_lon2 = (lon2 / COORDINATE_PRECISION) * detail::DEGREE_TO_RAD;
|
||||
|
||||
const double x_value = (float_lon2 - float_lon1) * std::cos((float_lat1 + float_lat2) / 2.0);
|
||||
const double y_value = float_lat2 - float_lat1;
|
||||
return std::hypot(x_value, y_value) * detail::EARTH_RADIUS;
|
||||
}
|
||||
|
||||
double perpendicularDistance(const Coordinate segment_source,
|
||||
const Coordinate segment_target,
|
||||
const Coordinate query_location,
|
||||
@@ -153,7 +101,7 @@ double perpendicularDistance(const Coordinate segment_source,
|
||||
web_mercator::fromWGS84(query_location));
|
||||
nearest_location = web_mercator::toWGS84(projected_nearest);
|
||||
|
||||
const double approximate_distance = fccApproximateDistance(query_location, nearest_location);
|
||||
const double approximate_distance = greatCircleDistance(query_location, nearest_location);
|
||||
BOOST_ASSERT(0.0 <= approximate_distance);
|
||||
return approximate_distance;
|
||||
}
|
||||
@@ -179,30 +127,24 @@ Coordinate centroid(const Coordinate lhs, const Coordinate rhs)
|
||||
return centroid;
|
||||
}
|
||||
|
||||
double bearing(const Coordinate first_coordinate, const Coordinate second_coordinate)
|
||||
double bearing(const Coordinate coordinate_1, const Coordinate coordinate_2)
|
||||
{
|
||||
const double lon_diff =
|
||||
static_cast<double>(toFloating(second_coordinate.lon - first_coordinate.lon));
|
||||
const double lon_delta = detail::degToRad(lon_diff);
|
||||
const double lat1 = detail::degToRad(static_cast<double>(toFloating(first_coordinate.lat)));
|
||||
const double lat2 = detail::degToRad(static_cast<double>(toFloating(second_coordinate.lat)));
|
||||
const double y = std::sin(lon_delta) * std::cos(lat2);
|
||||
const double x =
|
||||
std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(lon_delta);
|
||||
double result = detail::radToDeg(std::atan2(y, x));
|
||||
while (result < 0.0)
|
||||
const auto lon1 = static_cast<double>(util::toFloating(coordinate_1.lon));
|
||||
const auto lat1 = static_cast<double>(util::toFloating(coordinate_1.lat));
|
||||
const auto lon2 = static_cast<double>(util::toFloating(coordinate_2.lon));
|
||||
const auto lat2 = static_cast<double>(util::toFloating(coordinate_2.lat));
|
||||
const auto &ruler = cheap_ruler_container.getRuler(coordinate_1.lat, coordinate_2.lat);
|
||||
auto result = ruler.bearing({lon1, lat1}, {lon2, lat2});
|
||||
if (result < 0.0)
|
||||
{
|
||||
result += 360.0;
|
||||
}
|
||||
BOOST_ASSERT(0 <= result && result <= 360);
|
||||
|
||||
while (result >= 360.0)
|
||||
{
|
||||
result -= 360.0;
|
||||
}
|
||||
// If someone gives us two identical coordinates, then the concept of a bearing
|
||||
// makes no sense. However, because it sometimes happens, we'll at least
|
||||
// return a consistent value of 0 so that the behaviour isn't random.
|
||||
BOOST_ASSERT(first_coordinate != second_coordinate || result == 0.);
|
||||
BOOST_ASSERT(coordinate_1 != coordinate_2 || result == 0.);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -322,7 +264,7 @@ double circleRadius(const Coordinate C1, const Coordinate C2, const Coordinate C
|
||||
// a circle by three points requires thee distinct points
|
||||
auto center = circleCenter(C1, C2, C3);
|
||||
if (center)
|
||||
return haversineDistance(C1, *center);
|
||||
return greatCircleDistance(C1, *center);
|
||||
else
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
@@ -372,8 +314,8 @@ double findClosestDistance(const Coordinate coordinate,
|
||||
const Coordinate segment_begin,
|
||||
const Coordinate segment_end)
|
||||
{
|
||||
return haversineDistance(coordinate,
|
||||
projectPointOnSegment(segment_begin, segment_end, coordinate).second);
|
||||
return greatCircleDistance(
|
||||
coordinate, projectPointOnSegment(segment_begin, segment_end, coordinate).second);
|
||||
}
|
||||
|
||||
// find the closes distance between two sets of coordinates
|
||||
@@ -437,7 +379,7 @@ Coordinate difference(const Coordinate lhs, const Coordinate rhs)
|
||||
|
||||
double computeArea(const std::vector<Coordinate> &polygon)
|
||||
{
|
||||
using util::coordinate_calculation::haversineDistance;
|
||||
using util::coordinate_calculation::greatCircleDistance;
|
||||
|
||||
if (polygon.empty())
|
||||
return 0.;
|
||||
@@ -458,15 +400,15 @@ double computeArea(const std::vector<Coordinate> &polygon)
|
||||
double area = 0.;
|
||||
auto first = polygon.begin();
|
||||
auto previous_base = util::Coordinate{first->lon, ref_latitude};
|
||||
auto previous_y = haversineDistance(previous_base, *first);
|
||||
auto previous_y = greatCircleDistance(previous_base, *first);
|
||||
for (++first; first != polygon.end(); ++first)
|
||||
{
|
||||
BOOST_ASSERT(first->lat >= ref_latitude);
|
||||
|
||||
const auto current_base = util::Coordinate{first->lon, ref_latitude};
|
||||
const auto current_y = haversineDistance(current_base, *first);
|
||||
const auto current_y = greatCircleDistance(current_base, *first);
|
||||
const auto chunk_area =
|
||||
haversineDistance(previous_base, current_base) * (previous_y + current_y);
|
||||
greatCircleDistance(previous_base, current_base) * (previous_y + current_y);
|
||||
|
||||
area += (current_base.lon >= previous_base.lon) ? chunk_area : -chunk_area;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user