Fixed nested offsets inside of the flatbuffers structure

This commit is contained in:
Denis Chaplygin 2019-08-15 15:39:02 +03:00
parent a9c187c99b
commit 97270ae473
5 changed files with 402 additions and 305 deletions

View File

@ -102,17 +102,23 @@ class BaseAPI
auto location = auto location =
fbresult::Position(static_cast<double>(util::toFloating(phantom.location.lon)), fbresult::Position(static_cast<double>(util::toFloating(phantom.location.lon)),
static_cast<double>(util::toFloating(phantom.location.lat))); static_cast<double>(util::toFloating(phantom.location.lat)));
auto name_string = builder.CreateString(
facade.GetNameForID(facade.GetNameIndex(phantom.forward_segment_id.id)).to_string());
boost::optional<flatbuffers::Offset<flatbuffers::String>> hint_string = boost::none;
if (parameters.generate_hints)
{
hint_string = builder.CreateString(Hint{phantom, facade.GetCheckSum()}.ToBase64());
}
fbresult::WaypointBuilder waypoint(builder); fbresult::WaypointBuilder waypoint(builder);
waypoint.add_location(&location); waypoint.add_location(&location);
waypoint.add_distance(util::coordinate_calculation::fccApproximateDistance( waypoint.add_distance(util::coordinate_calculation::fccApproximateDistance(
phantom.location, phantom.input_location)); phantom.location, phantom.input_location));
auto name_string = builder.CreateString(
facade.GetNameForID(facade.GetNameIndex(phantom.forward_segment_id.id)).to_string());
waypoint.add_name(name_string); waypoint.add_name(name_string);
if (parameters.generate_hints) if (hint_string)
{ {
auto hint_string = builder.CreateString(Hint{phantom, facade.GetCheckSum()}.ToBase64()); waypoint.add_hint(*hint_string);
waypoint.add_hint(hint_string);
} }
return waypoint; return waypoint;
} }

View File

@ -47,8 +47,6 @@ class NearestAPI final : public BaseAPI
void MakeResponse(const std::vector<std::vector<PhantomNodeWithDistance>> &phantom_nodes, void MakeResponse(const std::vector<std::vector<PhantomNodeWithDistance>> &phantom_nodes,
flatbuffers::FlatBufferBuilder &fb_result) const flatbuffers::FlatBufferBuilder &fb_result) const
{ {
fbresult::FBResultBuilder response(fb_result);
std::vector<flatbuffers::Offset<fbresult::Waypoint>> waypoints; std::vector<flatbuffers::Offset<fbresult::Waypoint>> waypoints;
waypoints.resize(phantom_nodes.front().size()); waypoints.resize(phantom_nodes.front().size());
std::transform(phantom_nodes.front().begin(), std::transform(phantom_nodes.front().begin(),
@ -67,6 +65,7 @@ class NearestAPI final : public BaseAPI
}); });
auto waypoints_vector = fb_result.CreateVector(waypoints); auto waypoints_vector = fb_result.CreateVector(waypoints);
fbresult::FBResultBuilder response(fb_result);
response.add_waypoints(waypoints_vector); response.add_waypoints(waypoints_vector);
fb_result.Finish(response.Finish()); fb_result.Finish(response.Finish());
} }

View File

@ -70,18 +70,23 @@ class RouteAPI : public BaseAPI
&all_start_end_points, // all used coordinates, ignoring waypoints= parameter &all_start_end_points, // all used coordinates, ignoring waypoints= parameter
flatbuffers::FlatBufferBuilder &fb_result) const flatbuffers::FlatBufferBuilder &fb_result) const
{ {
auto data_timestamp = facade.GetTimestamp();
boost::optional<flatbuffers::Offset<flatbuffers::String>> data_version_string = boost::none;
if (!data_timestamp.empty())
{
data_version_string = fb_result.CreateString(data_timestamp);
}
auto response = auto response =
MakeFBResponse(raw_routes, fb_result, [this, &all_start_end_points, &fb_result]() { MakeFBResponse(raw_routes, fb_result, [this, &all_start_end_points, &fb_result]() {
return BaseAPI::MakeWaypoints(fb_result, all_start_end_points); return BaseAPI::MakeWaypoints(fb_result, all_start_end_points);
}); });
auto data_timestamp = facade.GetTimestamp(); if (data_version_string)
if (!data_timestamp.empty())
{ {
auto data_version_string = fb_result.CreateString(data_timestamp); response.add_data_version(*data_version_string);
response.add_data_version(data_version_string);
} }
fb_result.Finish(response.Finish()); fb_result.Finish(response.Finish());
} }
@ -121,8 +126,6 @@ class RouteAPI : public BaseAPI
GetWptsFn getWaypoints) const GetWptsFn getWaypoints) const
{ {
fbresult::FBResultBuilder response(fb_result);
std::vector<flatbuffers::Offset<fbresult::RouteObject>> routes; std::vector<flatbuffers::Offset<fbresult::RouteObject>> routes;
for (const auto &raw_route : raw_routes.routes) for (const auto &raw_route : raw_routes.routes)
{ {
@ -136,37 +139,36 @@ class RouteAPI : public BaseAPI
raw_route.target_traversed_in_reverse)); raw_route.target_traversed_in_reverse));
} }
response.add_waypoints(getWaypoints());
auto routes_vector = fb_result.CreateVector(routes); auto routes_vector = fb_result.CreateVector(routes);
auto waypoints_vector = getWaypoints();
fbresult::FBResultBuilder response(fb_result);
response.add_routes(routes_vector); response.add_routes(routes_vector);
response.add_waypoints(waypoints_vector);
return response; return response;
} }
template <typename BuilderType, typename ForwardIter> template <typename ForwardIter>
void MakeGeometry(BuilderType builder, ForwardIter begin, ForwardIter end) const mapbox::util::variant<flatbuffers::Offset<flatbuffers::String>,
flatbuffers::Offset<flatbuffers::Vector<const fbresult::Position *>>>
MakeGeometry(flatbuffers::FlatBufferBuilder &builder, ForwardIter begin, ForwardIter end) const
{ {
if (parameters.geometries == RouteParameters::GeometriesType::Polyline) if (parameters.geometries == RouteParameters::GeometriesType::Polyline)
{ {
auto polyline_string = builder.fbb_.CreateString(encodePolyline<100000>(begin, end)); return builder.CreateString(encodePolyline<100000>(begin, end));
builder.add_polyline(polyline_string);
} }
else if (parameters.geometries == RouteParameters::GeometriesType::Polyline6) else if (parameters.geometries == RouteParameters::GeometriesType::Polyline6)
{ {
auto polyline_string = builder.fbb_.CreateString(encodePolyline<1000000>(begin, end)); return builder.CreateString(encodePolyline<1000000>(begin, end));
builder.add_polyline(polyline_string);
}
else
{
std::vector<fbresult::Position> coordinates;
coordinates.resize(std::distance(begin, end));
std::transform(begin, end, coordinates.begin(), [](const Coordinate &c) {
return fbresult::Position{static_cast<float>(util::toFloating(c.lon).__value),
static_cast<float>(util::toFloating(c.lat).__value)};
});
auto coordinates_vector = builder.fbb_.CreateVectorOfStructs(coordinates);
builder.add_coordinates(coordinates_vector);
} }
std::vector<fbresult::Position> coordinates;
coordinates.resize(std::distance(begin, end));
std::transform(begin, end, coordinates.begin(), [](const Coordinate &c) {
return fbresult::Position{static_cast<float>(util::toFloating(c.lon).__value),
static_cast<float>(util::toFloating(c.lat).__value)};
});
return builder.CreateVectorOfStructs(coordinates);
} }
boost::optional<util::json::Value> boost::optional<util::json::Value>
@ -313,6 +315,7 @@ class RouteAPI : public BaseAPI
} }
return result; return result;
} }
flatbuffers::Offset<fbresult::RouteObject> flatbuffers::Offset<fbresult::RouteObject>
MakeRoute(flatbuffers::FlatBufferBuilder &fb_result, MakeRoute(flatbuffers::FlatBufferBuilder &fb_result,
const std::vector<PhantomNodes> &segment_end_coordinates, const std::vector<PhantomNodes> &segment_end_coordinates,
@ -320,22 +323,13 @@ class RouteAPI : public BaseAPI
const std::vector<bool> &source_traversed_in_reverse, const std::vector<bool> &source_traversed_in_reverse,
const std::vector<bool> &target_traversed_in_reverse) const const std::vector<bool> &target_traversed_in_reverse) const
{ {
fbresult::RouteObjectBuilder routeObject(fb_result);
auto legs_info = MakeLegs(segment_end_coordinates, auto legs_info = MakeLegs(segment_end_coordinates,
unpacked_path_segments, unpacked_path_segments,
source_traversed_in_reverse, source_traversed_in_reverse,
target_traversed_in_reverse); target_traversed_in_reverse);
std::vector<guidance::RouteLeg> legs = legs_info.first; std::vector<guidance::RouteLeg> legs = legs_info.first;
std::vector<guidance::LegGeometry> leg_geometries = legs_info.second; std::vector<guidance::LegGeometry> leg_geometries = legs_info.second;
// Fill basix route info
auto route = guidance::assembleRoute(legs); auto route = guidance::assembleRoute(legs);
routeObject.add_distance(route.distance);
routeObject.add_duration(route.duration);
routeObject.add_weight(route.weight);
auto weight_name_string = fb_result.CreateString(facade.GetWeightName());
routeObject.add_weight_name(weight_name_string);
// Fill legs // Fill legs
std::vector<flatbuffers::Offset<fbresult::Leg>> routeLegs; std::vector<flatbuffers::Offset<fbresult::Leg>> routeLegs;
@ -344,166 +338,20 @@ class RouteAPI : public BaseAPI
{ {
auto leg = legs[idx]; auto leg = legs[idx];
auto &leg_geometry = leg_geometries[idx]; auto &leg_geometry = leg_geometries[idx];
fbresult::LegBuilder legBuilder(fb_result);
legBuilder.add_distance(leg.distance);
legBuilder.add_duration(leg.duration);
legBuilder.add_weight(leg.weight);
if (!leg.summary.empty())
{
auto summary_string = fb_result.CreateString(leg.summary);
legBuilder.add_summary(summary_string);
}
// Fill steps // Fill steps
std::vector<flatbuffers::Offset<fbresult::Step>> legSteps;
if (!leg.steps.empty()) if (!leg.steps.empty())
{ {
std::vector<flatbuffers::Offset<fbresult::Step>> legSteps;
legSteps.resize(leg.steps.size()); legSteps.resize(leg.steps.size());
std::transform( std::transform(leg.steps.begin(),
leg.steps.begin(), leg.steps.end(),
leg.steps.end(), legSteps.begin(),
legSteps.begin(), [this, &fb_result, &leg_geometry](auto &step) {
[this, &leg_geometry, &fb_result](const guidance::RouteStep &step) { return this->MakeFBStep(fb_result, leg_geometry, step);
fbresult::StepBuilder stepBuilder(fb_result); });
stepBuilder.add_duration(step.duration);
stepBuilder.add_distance(step.distance);
stepBuilder.add_weight(step.weight);
auto name_string = fb_result.CreateString(step.name);
stepBuilder.add_name(name_string);
if (!step.ref.empty())
{
auto ref_string = fb_result.CreateString(step.ref);
stepBuilder.add_ref(ref_string);
}
if (!step.pronunciation.empty())
{
auto pronunciation_string = fb_result.CreateString(step.pronunciation);
stepBuilder.add_pronunciation(pronunciation_string);
}
if (!step.destinations.empty())
{
auto destinations_string = fb_result.CreateString(step.destinations);
stepBuilder.add_destinations(destinations_string);
}
if (!step.exits.empty())
{
auto exists_string = fb_result.CreateString(step.exits);
stepBuilder.add_exits(exists_string);
}
if (!step.rotary_name.empty())
{
auto rotary_name_string = fb_result.CreateString(step.rotary_name);
stepBuilder.add_rotary_name(rotary_name_string);
if (!step.rotary_pronunciation.empty())
{
auto rotary_pronunciation_string =
fb_result.CreateString(step.rotary_pronunciation);
stepBuilder.add_rotary_pronunciation(rotary_pronunciation_string);
}
}
auto mode_string =
fb_result.CreateString(extractor::travelModeToString(step.mode));
stepBuilder.add_mode(mode_string);
stepBuilder.add_driving_side(step.is_left_hand_driving);
// Geometry
MakeGeometry(stepBuilder,
leg_geometry.locations.begin() + step.geometry_begin,
leg_geometry.locations.begin() + step.geometry_end);
// Maneuver
fbresult::StepManeuverBuilder maneuver(fb_result);
fbresult::Position maneuverPosition{
static_cast<float>(
util::toFloating(step.maneuver.location.lon).__value),
static_cast<float>(
util::toFloating(step.maneuver.location.lat).__value)};
maneuver.add_location(&maneuverPosition);
maneuver.add_bearing_before(step.maneuver.bearing_before);
maneuver.add_bearing_after(step.maneuver.bearing_after);
if (step.maneuver.waypoint_type == guidance::WaypointType::None)
maneuver.add_type(TurnTypeToFB(step.maneuver.instruction.type));
else
maneuver.add_type(WaypointTypeToFB(step.maneuver.waypoint_type));
if (osrm::engine::api::json::detail::isValidModifier(step.maneuver))
{
maneuver.add_modifier(
TurnModifierToFB(step.maneuver.instruction.direction_modifier));
}
if (step.maneuver.exit != 0)
{
maneuver.add_exit(step.maneuver.exit);
}
// intersections
std::vector<flatbuffers::Offset<fbresult::Intersection>> intersections;
intersections.resize(step.intersections.size());
std::transform(
step.intersections.begin(),
step.intersections.end(),
intersections.begin(),
[&fb_result,
this](const guidance::IntermediateIntersection &intersection) {
fbresult::IntersectionBuilder intersectionBuilder(fb_result);
fbresult::Position maneuverPosition{
static_cast<float>(
util::toFloating(intersection.location.lon).__value),
static_cast<float>(
util::toFloating(intersection.location.lat).__value)};
intersectionBuilder.add_location(&maneuverPosition);
auto bearings_vector =
fb_result.CreateVector(intersection.bearings);
intersectionBuilder.add_bearings(bearings_vector);
std::vector<flatbuffers::Offset<flatbuffers::String>> classes;
classes.resize(intersection.classes.size());
std::transform(intersection.classes.begin(),
intersection.classes.end(),
classes.begin(),
[&fb_result](const std::string cls) {
return fb_result.CreateString(cls);
});
auto classes_vector = fb_result.CreateVector(classes);
intersectionBuilder.add_classes(classes_vector);
auto entry_vector = fb_result.CreateVector(intersection.entry);
intersectionBuilder.add_entry(entry_vector);
intersectionBuilder.add_in(intersection.in);
intersectionBuilder.add_out(intersection.out);
if (api::json::detail::hasValidLanes(intersection))
{
BOOST_ASSERT(intersection.lanes.lanes_in_turn >= 1);
std::vector<flatbuffers::Offset<fbresult::Lane>> lanes;
lanes.resize(intersection.lane_description.size());
LaneID lane_id = intersection.lane_description.size();
for (const auto &lane_desc : intersection.lane_description)
{
--lane_id;
fbresult::LaneBuilder laneBuilder(fb_result);
auto indications_vector =
fb_result.CreateVector(TurnLaneTypeToFB(lane_desc));
laneBuilder.add_indications(indications_vector);
if (lane_id >=
intersection.lanes.first_lane_from_the_right &&
lane_id < intersection.lanes.first_lane_from_the_right +
intersection.lanes.lanes_in_turn)
laneBuilder.add_valid(true);
else
laneBuilder.add_valid(false);
lanes.emplace_back(laneBuilder.Finish());
}
auto lanes_vector = fb_result.CreateVector(lanes);
intersectionBuilder.add_lanes(lanes_vector);
}
return intersectionBuilder.Finish();
});
auto intersections_vector = fb_result.CreateVector(intersections);
stepBuilder.add_intersections(intersections_vector);
return stepBuilder.Finish();
});
auto steps_vector = fb_result.CreateVector(legSteps);
legBuilder.add_steps(steps_vector);
} }
auto steps_vector = fb_result.CreateVector(legSteps);
// Fill annotations // Fill annotations
// To maintain support for uses of the old default constructors, we check // To maintain support for uses of the old default constructors, we check
@ -515,113 +363,339 @@ class RouteAPI : public BaseAPI
requested_annotations = RouteParameters::AnnotationsType::All; requested_annotations = RouteParameters::AnnotationsType::All;
} }
boost::optional<flatbuffers::Offset<fbresult::Annotation>> annotation_buffer =
boost::none;
if (requested_annotations != RouteParameters::AnnotationsType::None) if (requested_annotations != RouteParameters::AnnotationsType::None)
{ {
fbresult::AnnotationBuilder annotation(fb_result); annotation_buffer =
MakeFBAnnotations(fb_result, leg_geometry, requested_annotations);
// AnnotationsType uses bit flags, & operator checks if a property is set
if (parameters.annotations_type & RouteParameters::AnnotationsType::Speed)
{
double prev_speed = 0;
auto speed = GetAnnotations<float>(
fb_result,
leg_geometry,
[&prev_speed](const guidance::LegGeometry::Annotation &anno) {
if (anno.duration < std::numeric_limits<float>::min())
{
return prev_speed;
}
else
{
auto speed = std::round(anno.distance / anno.duration * 10.) / 10.;
prev_speed = speed;
return util::json::clamp_float(speed);
}
});
annotation.add_speed(speed);
}
if (requested_annotations & RouteParameters::AnnotationsType::Duration)
{
auto duration = GetAnnotations<uint32_t>(
fb_result, leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return anno.duration;
});
annotation.add_duration(duration);
}
if (requested_annotations & RouteParameters::AnnotationsType::Distance)
{
auto distance = GetAnnotations<uint32_t>(
fb_result, leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return anno.distance;
});
annotation.add_distance(distance);
}
if (requested_annotations & RouteParameters::AnnotationsType::Weight)
{
auto weight = GetAnnotations<uint32_t>(
fb_result, leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return anno.weight;
});
annotation.add_weight(weight);
}
if (requested_annotations & RouteParameters::AnnotationsType::Datasources)
{
auto datasources = GetAnnotations<uint32_t>(
fb_result, leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return anno.datasource;
});
annotation.add_datasources(datasources);
}
if (requested_annotations & RouteParameters::AnnotationsType::Nodes)
{
std::vector<uint32_t> nodes;
nodes.reserve(leg_geometry.osm_node_ids.size());
for (const auto node_id : leg_geometry.osm_node_ids)
{
nodes.emplace_back(static_cast<std::uint64_t>(node_id));
}
auto nodes_vector = fb_result.CreateVector(nodes);
annotation.add_nodes(nodes_vector);
}
// Add any supporting metadata, if needed
if (requested_annotations & RouteParameters::AnnotationsType::Datasources)
{
const auto MAX_DATASOURCE_ID = 255u;
fbresult::MetadataBuilder metadata(fb_result);
std::vector<flatbuffers::Offset<flatbuffers::String>> names;
for (auto i = 0u; i < MAX_DATASOURCE_ID; i++)
{
const auto name = facade.GetDatasourceName(i);
// Length of 0 indicates the first empty name, so we can stop here
if (name.size() == 0)
break;
names.emplace_back(
fb_result.CreateString(std::string(facade.GetDatasourceName(i))));
}
auto datasource_names_vector = fb_result.CreateVector(names);
metadata.add_datasource_names(datasource_names_vector);
annotation.add_metadata(metadata.Finish());
}
legBuilder.add_annotations(annotation.Finish());
} }
flatbuffers::Offset<flatbuffers::String> summary_string;
if (!leg.summary.empty())
{
summary_string = fb_result.CreateString(leg.summary);
}
fbresult::LegBuilder legBuilder(fb_result);
legBuilder.add_distance(leg.distance);
legBuilder.add_duration(leg.duration);
legBuilder.add_weight(leg.weight);
if (!leg.summary.empty())
{
legBuilder.add_summary(summary_string);
}
legBuilder.add_steps(steps_vector);
if (annotation_buffer)
{
legBuilder.add_annotations(*annotation_buffer);
}
routeLegs.emplace_back(legBuilder.Finish()); routeLegs.emplace_back(legBuilder.Finish());
} }
auto legs_vector = fb_result.CreateVector(routeLegs); auto legs_vector = fb_result.CreateVector(routeLegs);
routeObject.add_legs(legs_vector);
// Fill geometry // Fill geometry
auto overview = MakeOverview(leg_geometries); auto overview = MakeOverview(leg_geometries);
mapbox::util::variant<flatbuffers::Offset<flatbuffers::String>,
flatbuffers::Offset<flatbuffers::Vector<const fbresult::Position *>>>
geometry;
if (overview) if (overview)
{ {
MakeGeometry(routeObject, overview->begin(), overview->end()); geometry = MakeGeometry(fb_result, overview->begin(), overview->end());
}
auto weight_name_string = fb_result.CreateString(facade.GetWeightName());
fbresult::RouteObjectBuilder routeObject(fb_result);
routeObject.add_distance(route.distance);
routeObject.add_duration(route.duration);
routeObject.add_weight(route.weight);
routeObject.add_weight_name(weight_name_string);
routeObject.add_legs(legs_vector);
if (overview)
{
mapbox::util::apply_visitor(GeometryVisitor<fbresult::RouteObjectBuilder>(routeObject),
geometry);
} }
return routeObject.Finish(); return routeObject.Finish();
} }
flatbuffers::Offset<fbresult::Annotation>
MakeFBAnnotations(flatbuffers::FlatBufferBuilder &fb_result,
guidance::LegGeometry &leg_geometry,
const RouteParameters::AnnotationsType &requested_annotations) const
{
// AnnotationsType uses bit flags, & operator checks if a property is set
flatbuffers::Offset<flatbuffers::Vector<float>> speed;
if (parameters.annotations_type & RouteParameters::AnnotationsType::Speed)
{
double prev_speed = 0;
speed =
GetAnnotations<float>(fb_result,
leg_geometry,
[&prev_speed](const guidance::LegGeometry::Annotation &anno) {
if (anno.duration < std::numeric_limits<float>::min())
{
return prev_speed;
}
else
{
auto speed =
round(anno.distance / anno.duration * 10.) / 10.;
prev_speed = speed;
return util::json::clamp_float(speed);
}
});
}
flatbuffers::Offset<flatbuffers::Vector<uint32_t>> duration;
if (requested_annotations & RouteParameters::AnnotationsType::Duration)
{
duration = GetAnnotations<uint32_t>(
fb_result, leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return anno.duration;
});
}
flatbuffers::Offset<flatbuffers::Vector<uint32_t>> distance;
if (requested_annotations & RouteParameters::AnnotationsType::Distance)
{
distance = GetAnnotations<uint32_t>(
fb_result, leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return anno.distance;
});
}
flatbuffers::Offset<flatbuffers::Vector<uint32_t>> weight;
if (requested_annotations & RouteParameters::AnnotationsType::Weight)
{
weight = GetAnnotations<uint32_t>(
fb_result, leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return anno.weight;
});
}
flatbuffers::Offset<flatbuffers::Vector<uint32_t>> datasources;
if (requested_annotations & RouteParameters::AnnotationsType::Datasources)
{
datasources = GetAnnotations<uint32_t>(
fb_result, leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return anno.datasource;
});
}
std::vector<uint32_t> nodes;
if (requested_annotations & RouteParameters::AnnotationsType::Nodes)
{
nodes.reserve(leg_geometry.osm_node_ids.size());
for (const auto node_id : leg_geometry.osm_node_ids)
{
nodes.emplace_back(static_cast<uint64_t>(node_id));
}
}
auto nodes_vector = fb_result.CreateVector(nodes);
// Add any supporting metadata, if needed
boost::optional<flatbuffers::Offset<fbresult::Metadata>> metadata_buffer = boost::none;
if (requested_annotations & RouteParameters::AnnotationsType::Datasources)
{
const auto MAX_DATASOURCE_ID = 255u;
std::vector<flatbuffers::Offset<flatbuffers::String>> names;
for (auto i = 0u; i < MAX_DATASOURCE_ID; i++)
{
const auto name = facade.GetDatasourceName(i);
// Length of 0 indicates the first empty name, so we can stop here
if (name.size() == 0)
break;
names.emplace_back(
fb_result.CreateString(std::string(facade.GetDatasourceName(i))));
}
metadata_buffer = fbresult::CreateMetadataDirect(fb_result, &names);
}
fbresult::AnnotationBuilder annotation(fb_result);
annotation.add_speed(speed);
annotation.add_duration(duration);
annotation.add_distance(distance);
annotation.add_weight(weight);
annotation.add_datasources(datasources);
annotation.add_nodes(nodes_vector);
if (metadata_buffer)
{
annotation.add_metadata(*metadata_buffer);
}
return annotation.Finish();
}
template <typename Builder> class GeometryVisitor
{
public:
GeometryVisitor(Builder &builder) : builder(builder) {}
void operator()(const flatbuffers::Offset<flatbuffers::String> &value)
{
builder.add_polyline(value);
}
void operator()(
const flatbuffers::Offset<flatbuffers::Vector<const fbresult::Position *>> &value)
{
builder.add_coordinates(value);
}
private:
Builder &builder;
};
flatbuffers::Offset<fbresult::Step> MakeFBStep(flatbuffers::FlatBufferBuilder &builder,
const guidance::LegGeometry &leg_geometry,
const guidance::RouteStep &step) const
{
auto name_string = builder.CreateString(step.name);
flatbuffers::Offset<flatbuffers::String> ref_string;
if (!step.ref.empty())
{
ref_string = builder.CreateString(step.ref);
}
flatbuffers::Offset<flatbuffers::String> pronunciation_string;
if (!step.pronunciation.empty())
{
pronunciation_string = builder.CreateString(step.pronunciation);
}
flatbuffers::Offset<flatbuffers::String> destinations_string;
if (!step.destinations.empty())
{
destinations_string = builder.CreateString(step.destinations);
}
flatbuffers::Offset<flatbuffers::String> exists_string;
if (!step.exits.empty())
{
exists_string = builder.CreateString(step.exits);
}
flatbuffers::Offset<flatbuffers::String> rotary_name_string;
flatbuffers::Offset<flatbuffers::String> rotary_pronunciation_string;
if (!step.rotary_name.empty())
{
rotary_name_string = builder.CreateString(step.rotary_name);
if (!step.rotary_pronunciation.empty())
{
rotary_pronunciation_string = builder.CreateString(step.rotary_pronunciation);
}
}
auto mode_string = builder.CreateString(extractor::travelModeToString(step.mode));
// Geometry
auto geometry = MakeGeometry(builder,
leg_geometry.locations.begin() + step.geometry_begin,
leg_geometry.locations.begin() + step.geometry_end);
// Maneuver
fbresult::StepManeuverBuilder maneuver(builder);
fbresult::Position maneuverPosition{
static_cast<float>(util::toFloating(step.maneuver.location.lon).__value),
static_cast<float>(util::toFloating(step.maneuver.location.lat).__value)};
maneuver.add_location(&maneuverPosition);
maneuver.add_bearing_before(step.maneuver.bearing_before);
maneuver.add_bearing_after(step.maneuver.bearing_after);
if (step.maneuver.waypoint_type == guidance::WaypointType::None)
maneuver.add_type(TurnTypeToFB(step.maneuver.instruction.type));
else
maneuver.add_type(WaypointTypeToFB(step.maneuver.waypoint_type));
if (osrm::engine::api::json::detail::isValidModifier(step.maneuver))
{
maneuver.add_modifier(TurnModifierToFB(step.maneuver.instruction.direction_modifier));
}
if (step.maneuver.exit != 0)
{
maneuver.add_exit(step.maneuver.exit);
}
auto maneuver_buffer = maneuver.Finish();
// intersections
auto intersections_vector = MakeFBIntersections(builder, step);
fbresult::StepBuilder stepBuilder(builder);
stepBuilder.add_duration(step.duration);
stepBuilder.add_distance(step.distance);
stepBuilder.add_weight(step.weight);
stepBuilder.add_name(name_string);
stepBuilder.add_mode(mode_string);
stepBuilder.add_driving_side(step.is_left_hand_driving);
stepBuilder.add_ref(ref_string);
stepBuilder.add_pronunciation(pronunciation_string);
stepBuilder.add_destinations(destinations_string);
stepBuilder.add_exits(exists_string);
stepBuilder.add_rotary_name(rotary_name_string);
stepBuilder.add_rotary_pronunciation(rotary_pronunciation_string);
stepBuilder.add_intersections(intersections_vector);
stepBuilder.add_maneuver(maneuver_buffer);
mapbox::util::apply_visitor(GeometryVisitor<fbresult::StepBuilder>(stepBuilder), geometry);
return stepBuilder.Finish();
};
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<fbresult::Intersection>>>
MakeFBIntersections(flatbuffers::FlatBufferBuilder &fb_result,
const guidance::RouteStep &step) const
{
std::vector<flatbuffers::Offset<fbresult::Intersection>> intersections;
intersections.resize(step.intersections.size());
std::transform(
step.intersections.begin(),
step.intersections.end(),
intersections.begin(),
[&fb_result, this](const guidance::IntermediateIntersection &intersection) {
std::vector<flatbuffers::Offset<fbresult::Lane>> lanes;
if (json::detail::hasValidLanes(intersection))
{
BOOST_ASSERT(intersection.lanes.lanes_in_turn >= 1);
lanes.reserve(intersection.lane_description.size());
LaneID lane_id = intersection.lane_description.size();
for (const auto &lane_desc : intersection.lane_description)
{
--lane_id;
auto indications = TurnLaneTypeToFB(lane_desc);
auto lane_valid = lane_id >= intersection.lanes.first_lane_from_the_right &&
lane_id < intersection.lanes.first_lane_from_the_right +
intersection.lanes.lanes_in_turn;
lanes.push_back(
fbresult::CreateLaneDirect(fb_result, &indications, lane_valid));
}
}
auto lanes_vector = fb_result.CreateVector(lanes);
fbresult::Position maneuverPosition{
static_cast<float>(util::toFloating(intersection.location.lon).__value),
static_cast<float>(util::toFloating(intersection.location.lat).__value)};
auto bearings_vector = fb_result.CreateVector(intersection.bearings);
std::vector<flatbuffers::Offset<flatbuffers::String>> classes;
classes.resize(intersection.classes.size());
std::transform(
intersection.classes.begin(),
intersection.classes.end(),
classes.begin(),
[&fb_result](const std::string cls) { return fb_result.CreateString(cls); });
auto classes_vector = fb_result.CreateVector(classes);
auto entry_vector = fb_result.CreateVector(intersection.entry);
fbresult::IntersectionBuilder intersectionBuilder(fb_result);
intersectionBuilder.add_location(&maneuverPosition);
intersectionBuilder.add_bearings(bearings_vector);
intersectionBuilder.add_classes(classes_vector);
intersectionBuilder.add_entry(entry_vector);
intersectionBuilder.add_in(intersection.in);
intersectionBuilder.add_out(intersection.out);
intersectionBuilder.add_lanes(lanes_vector);
return intersectionBuilder.Finish();
});
return fb_result.CreateVector(intersections);
}
util::json::Object MakeRoute(const std::vector<PhantomNodes> &segment_end_coordinates, util::json::Object MakeRoute(const std::vector<PhantomNodes> &segment_end_coordinates,
const std::vector<std::vector<PathData>> &unpacked_path_segments, const std::vector<std::vector<PathData>> &unpacked_path_segments,
const std::vector<bool> &source_traversed_in_reverse, const std::vector<bool> &source_traversed_in_reverse,

View File

@ -72,50 +72,71 @@ class TableAPI final : public BaseAPI
auto number_of_sources = parameters.sources.size(); auto number_of_sources = parameters.sources.size();
auto number_of_destinations = parameters.destinations.size(); auto number_of_destinations = parameters.destinations.size();
fbresult::FBResultBuilder response(fb_result);
fbresult::TableBuilder table(fb_result);
// symmetric case // symmetric case
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<fbresult::Waypoint>>> sources;
if (parameters.sources.empty()) if (parameters.sources.empty())
{ {
response.add_waypoints(MakeWaypoints(fb_result, phantoms)); sources = MakeWaypoints(fb_result, phantoms);
number_of_sources = phantoms.size(); number_of_sources = phantoms.size();
} }
else else
{ {
response.add_waypoints(MakeWaypoints(fb_result, phantoms, parameters.sources)); sources = MakeWaypoints(fb_result, phantoms, parameters.sources);
} }
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<fbresult::Waypoint>>>
destinations;
if (parameters.destinations.empty()) if (parameters.destinations.empty())
{ {
table.add_destinations(MakeWaypoints(fb_result, phantoms)); destinations = MakeWaypoints(fb_result, phantoms);
number_of_destinations = phantoms.size(); number_of_destinations = phantoms.size();
} }
else else
{ {
table.add_destinations(MakeWaypoints(fb_result, phantoms, parameters.destinations)); destinations = MakeWaypoints(fb_result, phantoms, parameters.destinations);
} }
boost::optional<flatbuffers::Offset<flatbuffers::Vector<float>>> durations = boost::none;
if (parameters.annotations & TableParameters::AnnotationsType::Duration) if (parameters.annotations & TableParameters::AnnotationsType::Duration)
{ {
table.add_durations(MakeDurationTable(fb_result, tables.first)); durations = MakeDurationTable(fb_result, tables.first);
} }
boost::optional<flatbuffers::Offset<flatbuffers::Vector<float>>> distances = boost::none;
if (parameters.annotations & TableParameters::AnnotationsType::Distance) if (parameters.annotations & TableParameters::AnnotationsType::Distance)
{ {
table.add_distances(MakeDistanceTable(fb_result, tables.second)); distances = MakeDistanceTable(fb_result, tables.second);
} }
boost::optional<flatbuffers::Offset<flatbuffers::Vector<uint32_t>>> speed_cells =
boost::none;
if (parameters.fallback_speed != INVALID_FALLBACK_SPEED && parameters.fallback_speed > 0) if (parameters.fallback_speed != INVALID_FALLBACK_SPEED && parameters.fallback_speed > 0)
{ {
table.add_fallback_speed_cells(MakeEstimatesTable(fb_result, fallback_speed_cells)); speed_cells = MakeEstimatesTable(fb_result, fallback_speed_cells);
} }
fbresult::TableBuilder table(fb_result);
table.add_destinations(destinations);
table.add_rows(number_of_sources); table.add_rows(number_of_sources);
table.add_cols(number_of_destinations); table.add_cols(number_of_destinations);
if (durations)
{
table.add_durations(*durations);
}
if (distances)
{
table.add_distances(*distances);
}
if (speed_cells)
{
table.add_fallback_speed_cells(*speed_cells);
}
auto table_buffer = table.Finish();
response.add_table(table.Finish()); fbresult::FBResultBuilder response(fb_result);
response.add_table(table_buffer);
response.add_waypoints(sources);
fb_result.Finish(response.Finish()); fb_result.Finish(response.Finish());
} }

View File

@ -79,14 +79,11 @@ class BasePlugin
}; };
void operator()(flatbuffers::FlatBufferBuilder &fb_result) void operator()(flatbuffers::FlatBufferBuilder &fb_result)
{ {
api::fbresult::FBResultBuilder error(fb_result); auto error = api::fbresult::CreateErrorDirect(fb_result, code.c_str(), message.c_str());
error.add_error(true); api::fbresult::FBResultBuilder response(fb_result);
response.add_error(true);
api::fbresult::ErrorBuilder codeBuilder(fb_result); response.add_code(error);
codeBuilder.add_code(fb_result.CreateString(code)); fb_result.Finish(response.Finish());
codeBuilder.add_message(fb_result.CreateString(message));
error.add_code(codeBuilder.Finish());
fb_result.Finish(error.Finish());
}; };
void operator()(std::string &str_result) void operator()(std::string &str_result)
{ {