osrm-backend/include/engine/plugins/distance_table.hpp

221 lines
9.4 KiB
C++
Raw Normal View History

2015-01-27 11:44:46 -05:00
#ifndef DISTANCE_TABLE_HPP
#define DISTANCE_TABLE_HPP
2016-01-02 11:13:44 -05:00
#include "engine/plugins/plugin_base.hpp"
#include "engine/object_encoder.hpp"
#include "contractor/query_edge.hpp"
#include "engine/search_engine.hpp"
#include "engine/descriptors/descriptor_base.hpp"
#include "util/json_renderer.hpp"
#include "util/make_unique.hpp"
#include "util/string_util.hpp"
#include "util/timing_util.hpp"
#include "osrm/json_container.hpp"
2014-11-24 11:57:01 -05:00
#include <cstdlib>
#include <algorithm>
#include <memory>
#include <unordered_map>
#include <string>
#include <vector>
2014-10-13 11:29:53 -04:00
template <class DataFacadeT> class DistanceTablePlugin final : public BasePlugin
{
private:
std::unique_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
int max_locations_distance_table;
public:
2015-01-27 11:44:46 -05:00
explicit DistanceTablePlugin(DataFacadeT *facade, const int max_locations_distance_table)
: max_locations_distance_table(max_locations_distance_table), descriptor_string("table"),
facade(facade)
{
search_engine_ptr = osrm::make_unique<SearchEngine<DataFacadeT>>(facade);
}
virtual ~DistanceTablePlugin() {}
const std::string GetDescriptor() const override final { return descriptor_string; }
2015-12-17 10:45:15 -05:00
Status HandleRequest(const RouteParameters &route_parameters,
osrm::json::Object &json_result) override final
{
2015-12-07 21:16:07 -05:00
if (!check_all_coordinates(route_parameters.coordinates))
{
2015-12-18 12:18:48 -05:00
json_result.values["status_message"] = "Coordinates are invalid";
2015-12-17 10:45:15 -05:00
return Status::Error;
}
2015-12-07 21:16:07 -05:00
const auto &input_bearings = route_parameters.bearings;
if (input_bearings.size() > 0 &&
route_parameters.coordinates.size() != input_bearings.size())
{
2015-12-07 21:16:07 -05:00
json_result.values["status_message"] =
2015-12-18 12:18:48 -05:00
"Number of bearings does not match number of coordinates";
2015-12-17 10:45:15 -05:00
return Status::Error;
}
2015-12-07 21:16:07 -05:00
auto number_of_sources =
std::count_if(route_parameters.is_source.begin(), route_parameters.is_source.end(),
[](const bool is_source)
{
return is_source;
});
auto number_of_destination =
std::count_if(route_parameters.is_destination.begin(),
route_parameters.is_destination.end(), [](const bool is_destination)
{
return is_destination;
});
if (max_locations_distance_table > 0 &&
(number_of_sources * number_of_destination >
max_locations_distance_table * max_locations_distance_table))
{
2015-12-07 21:16:07 -05:00
json_result.values["status_message"] =
"Number of entries " + std::to_string(number_of_sources * number_of_destination) +
" is higher than current maximum (" +
std::to_string(max_locations_distance_table * max_locations_distance_table) + ")";
2015-12-17 10:45:15 -05:00
return Status::Error;
}
2015-01-05 06:59:29 -05:00
const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum());
2015-12-07 21:16:07 -05:00
std::vector<PhantomNodePair> phantom_node_source_vector(number_of_sources);
std::vector<PhantomNodePair> phantom_node_target_vector(number_of_destination);
2015-12-07 21:16:07 -05:00
auto phantom_node_source_out_iter = phantom_node_source_vector.begin();
auto phantom_node_target_out_iter = phantom_node_target_vector.begin();
for (const auto i : osrm::irange<std::size_t>(0u, route_parameters.coordinates.size()))
{
2015-01-05 06:59:29 -05:00
if (checksum_OK && i < route_parameters.hints.size() &&
!route_parameters.hints[i].empty())
{
PhantomNode current_phantom_node;
ObjectEncoder::DecodeFromBase64(route_parameters.hints[i], current_phantom_node);
if (current_phantom_node.is_valid(facade->GetNumberOfNodes()))
{
2015-12-07 21:16:07 -05:00
if (route_parameters.is_source[i])
{
*phantom_node_source_out_iter =
std::make_pair(current_phantom_node, current_phantom_node);
2015-12-07 21:16:07 -05:00
if (route_parameters.is_destination[i])
{
*phantom_node_target_out_iter = *phantom_node_source_out_iter;
phantom_node_target_out_iter++;
}
phantom_node_source_out_iter++;
}
else
{
BOOST_ASSERT(route_parameters.is_destination[i] &&
!route_parameters.is_source[i]);
*phantom_node_target_out_iter =
std::make_pair(current_phantom_node, current_phantom_node);
2015-12-07 21:16:07 -05:00
phantom_node_target_out_iter++;
}
2015-01-05 06:59:29 -05:00
continue;
}
}
const int bearing = input_bearings.size() > 0 ? input_bearings[i].first : 0;
2015-12-07 21:16:07 -05:00
const int range = input_bearings.size() > 0
? (input_bearings[i].second ? *input_bearings[i].second : 10)
: 180;
if (route_parameters.is_source[i])
{
*phantom_node_source_out_iter =
facade->NearestPhantomNodeWithAlternativeFromBigComponent(
route_parameters.coordinates[i], bearing, range);
// we didn't found a fitting node, return error
if (!phantom_node_source_out_iter->first.is_valid(facade->GetNumberOfNodes()))
{
json_result.values["status_message"] =
std::string("Could not find a matching segment for coordinate ") + std::to_string(i);
2015-12-17 10:45:15 -05:00
return Status::NoSegment;
}
2015-12-07 21:16:07 -05:00
if (route_parameters.is_destination[i])
{
2015-12-07 21:16:07 -05:00
*phantom_node_target_out_iter = *phantom_node_source_out_iter;
phantom_node_target_out_iter++;
}
2015-12-07 21:16:07 -05:00
phantom_node_source_out_iter++;
}
else
{
BOOST_ASSERT(route_parameters.is_destination[i] && !route_parameters.is_source[i]);
*phantom_node_target_out_iter =
facade->NearestPhantomNodeWithAlternativeFromBigComponent(
route_parameters.coordinates[i], bearing, range);
// we didn't found a fitting node, return error
if (!phantom_node_target_out_iter->first.is_valid(facade->GetNumberOfNodes()))
{
json_result.values["status_message"] =
std::string("Could not find a matching segment for coordinate ") + std::to_string(i);
2015-12-17 10:45:15 -05:00
return Status::NoSegment;
}
2015-12-07 21:16:07 -05:00
phantom_node_target_out_iter++;
}
}
2015-12-07 21:16:07 -05:00
BOOST_ASSERT((phantom_node_source_out_iter - phantom_node_source_vector.begin()) ==
number_of_sources);
BOOST_ASSERT((phantom_node_target_out_iter - phantom_node_target_vector.begin()) ==
number_of_destination);
// FIXME we should clear phantom_node_source_vector and phantom_node_target_vector after
// this
auto snapped_source_phantoms = snapPhantomNodes(phantom_node_source_vector);
auto snapped_target_phantoms = snapPhantomNodes(phantom_node_target_vector);
auto result_table =
search_engine_ptr->distance_table(snapped_source_phantoms, snapped_target_phantoms);
if (!result_table)
{
2015-12-18 12:18:48 -05:00
json_result.values["status_message"] = "No distance table found";
2015-12-17 10:45:15 -05:00
return Status::EmptyResult;
}
2015-01-02 09:46:43 -05:00
osrm::json::Array matrix_json_array;
for (const auto row : osrm::irange<std::size_t>(0, number_of_sources))
{
osrm::json::Array json_row;
2015-12-07 21:16:07 -05:00
auto row_begin_iterator = result_table->begin() + (row * number_of_destination);
auto row_end_iterator = result_table->begin() + ((row + 1) * number_of_destination);
json_row.values.insert(json_row.values.end(), row_begin_iterator, row_end_iterator);
matrix_json_array.values.push_back(json_row);
}
json_result.values["distance_table"] = matrix_json_array;
2015-12-07 21:16:07 -05:00
osrm::json::Array target_coord_json_array;
for (const auto &phantom : snapped_target_phantoms)
2015-12-07 21:16:07 -05:00
{
osrm::json::Array json_coord;
json_coord.values.push_back(phantom.location.lat / COORDINATE_PRECISION);
json_coord.values.push_back(phantom.location.lon / COORDINATE_PRECISION);
2015-12-07 21:16:07 -05:00
target_coord_json_array.values.push_back(json_coord);
}
json_result.values["destination_coordinates"] = target_coord_json_array;
osrm::json::Array source_coord_json_array;
for (const auto &phantom : snapped_source_phantoms)
2015-12-07 21:16:07 -05:00
{
osrm::json::Array json_coord;
json_coord.values.push_back(phantom.location.lat / COORDINATE_PRECISION);
json_coord.values.push_back(phantom.location.lon / COORDINATE_PRECISION);
2015-12-07 21:16:07 -05:00
source_coord_json_array.values.push_back(json_coord);
}
2015-12-07 21:16:07 -05:00
json_result.values["source_coordinates"] = source_coord_json_array;
2015-12-17 10:45:15 -05:00
return Status::Ok;
}
private:
std::string descriptor_string;
DataFacadeT *facade;
};
2015-01-27 11:44:46 -05:00
#endif // DISTANCE_TABLE_HPP