forked from organicmaps/organicmaps
Merge pull request #4672 from dobriy-eeh/index-routing
Indexed AStar routing
This commit is contained in:
commit
4492f89b9d
49 changed files with 2116 additions and 97 deletions
|
@ -27,6 +27,7 @@
|
|||
#define METADATA_FILE_TAG "meta"
|
||||
#define METADATA_INDEX_FILE_TAG "metaidx"
|
||||
#define ALTITUDES_FILE_TAG "altitudes"
|
||||
#define RESTRICTIONS_FILE_TAG "restrictions"
|
||||
#define ROUTING_FILE_TAG "routing"
|
||||
#define FEATURE_OFFSETS_FILE_TAG "offs"
|
||||
#define RANKS_FILE_TAG "ranks"
|
||||
|
@ -40,8 +41,6 @@
|
|||
#define ROUTING_SHORTCUTS_FILE_TAG "skoda"
|
||||
#define ROUTING_CROSS_CONTEXT_TAG "chrysler"
|
||||
|
||||
#define ROUTING_FILE_TAG "routing"
|
||||
|
||||
#define ROUTING_FTSEG_FILE_TAG "ftseg"
|
||||
#define ROUTING_NODEIND_TO_FTSEGIND_FILE_TAG "node2ftseg"
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ SOURCES += \
|
|||
restriction_generator.cpp \
|
||||
restriction_writer.cpp \
|
||||
routing_generator.cpp \
|
||||
routing_index_generator.cpp \
|
||||
search_index_builder.cpp \
|
||||
sponsored_scoring.cpp \
|
||||
srtm_parser.cpp \
|
||||
|
@ -80,6 +81,7 @@ HEADERS += \
|
|||
restriction_generator.hpp \
|
||||
restriction_writer.hpp \
|
||||
routing_generator.hpp \
|
||||
routing_index_generator.hpp \
|
||||
search_index_builder.hpp \
|
||||
sponsored_dataset.hpp \
|
||||
sponsored_dataset_inl.hpp \
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "generator/osm_source.hpp"
|
||||
#include "generator/restriction_generator.hpp"
|
||||
#include "generator/routing_generator.hpp"
|
||||
#include "generator/routing_index_generator.hpp"
|
||||
#include "generator/search_index_builder.hpp"
|
||||
#include "generator/statistics.hpp"
|
||||
#include "generator/unpack_mwm.hpp"
|
||||
|
@ -87,6 +88,7 @@ DEFINE_string(restriction_name, "", "Name of file with relation restriction in o
|
|||
DEFINE_string(feature_ids_to_osm_ids_name, "",
|
||||
"Name of file with mapping from feature ids to osm ids.");
|
||||
DEFINE_bool(generate_routing, false, "Generate section with routing information.");
|
||||
DEFINE_bool(generate_restrictions, false, "Generate section with road restrictions.");
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
|
@ -150,7 +152,7 @@ int main(int argc, char ** argv)
|
|||
FLAGS_generate_index || FLAGS_generate_search_index || FLAGS_calc_statistics ||
|
||||
FLAGS_type_statistics || FLAGS_dump_types || FLAGS_dump_prefixes ||
|
||||
FLAGS_dump_feature_names != "" || FLAGS_check_mwm || FLAGS_srtm_path != "" ||
|
||||
FLAGS_generate_routing)
|
||||
FLAGS_generate_routing || FLAGS_generate_restrictions )
|
||||
{
|
||||
classificator::Load();
|
||||
classif().SortClassificator();
|
||||
|
@ -237,8 +239,10 @@ int main(int argc, char ** argv)
|
|||
if (!FLAGS_srtm_path.empty())
|
||||
routing::BuildRoadAltitudes(datFile, FLAGS_srtm_path);
|
||||
|
||||
// @TODO(bykoianko) generate_routing flag should be used for all routing information.
|
||||
if (FLAGS_generate_routing)
|
||||
routing::BuildRoutingIndex(datFile);
|
||||
|
||||
if (FLAGS_generate_restrictions)
|
||||
{
|
||||
routing::BuildRoadRestrictions(
|
||||
datFile, genInfo.GetIntermediateFileName(genInfo.m_restrictions, "" /* extention */),
|
||||
|
|
|
@ -39,7 +39,7 @@ bool BuildRoadRestrictions(string const & mwmPath, string const & restrictionPat
|
|||
header.m_onlyRestrictionCount, "of type Only restrictions"));
|
||||
|
||||
FilesContainerW cont(mwmPath, FileWriter::OP_WRITE_EXISTING);
|
||||
FileWriter w = cont.GetWriter(ROUTING_FILE_TAG);
|
||||
FileWriter w = cont.GetWriter(RESTRICTIONS_FILE_TAG);
|
||||
header.Serialize(w);
|
||||
|
||||
RestrictionSerializer::Serialize(header, restrictions.cbegin(), restrictions.cend(), w);
|
||||
|
|
94
generator/routing_index_generator.cpp
Normal file
94
generator/routing_index_generator.cpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
#include "generator/routing_index_generator.hpp"
|
||||
|
||||
#include "routing/index_graph.hpp"
|
||||
#include "routing/routing_helpers.hpp"
|
||||
|
||||
#include "indexer/feature.hpp"
|
||||
#include "indexer/feature_processor.hpp"
|
||||
#include "indexer/point_to_int64.hpp"
|
||||
#include "indexer/routing_section.hpp"
|
||||
|
||||
#include "coding/file_container.hpp"
|
||||
|
||||
#include "base/logging.hpp"
|
||||
|
||||
#include "std/bind.hpp"
|
||||
#include "std/unordered_map.hpp"
|
||||
#include "std/vector.hpp"
|
||||
|
||||
using namespace feature;
|
||||
using namespace platform;
|
||||
using namespace routing;
|
||||
|
||||
namespace
|
||||
{
|
||||
class Processor final
|
||||
{
|
||||
public:
|
||||
void ProcessAllFeatures(string const & filename)
|
||||
{
|
||||
feature::ForEachFromDat(filename, bind(&Processor::ProcessFeature, this, _1, _2));
|
||||
}
|
||||
|
||||
void BuildGraph(IndexGraph & graph) const
|
||||
{
|
||||
vector<Joint> joints;
|
||||
for (auto const & it : m_posToJoint)
|
||||
{
|
||||
// Need only connected points (2 or more roads)
|
||||
if (it.second.GetSize() >= 2)
|
||||
joints.emplace_back(it.second);
|
||||
}
|
||||
|
||||
graph.Import(joints);
|
||||
}
|
||||
|
||||
private:
|
||||
void ProcessFeature(FeatureType const & f, uint32_t id)
|
||||
{
|
||||
if (!IsRoad(feature::TypesHolder(f)))
|
||||
return;
|
||||
|
||||
f.ParseGeometry(FeatureType::BEST_GEOMETRY);
|
||||
|
||||
for (size_t i = 0; i < f.GetPointsCount(); ++i)
|
||||
{
|
||||
uint64_t const locationKey = PointToInt64(f.GetPoint(i), POINT_COORD_BITS);
|
||||
m_posToJoint[locationKey].AddPoint(RoadPoint(id, i));
|
||||
}
|
||||
}
|
||||
|
||||
unordered_map<uint64_t, Joint> m_posToJoint;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace routing
|
||||
{
|
||||
bool BuildRoutingIndex(string const & filename)
|
||||
{
|
||||
LOG(LINFO, ("Building routing index for", filename));
|
||||
try
|
||||
{
|
||||
Processor processor;
|
||||
processor.ProcessAllFeatures(filename);
|
||||
|
||||
IndexGraph graph;
|
||||
processor.BuildGraph(graph);
|
||||
LOG(LINFO, ("Routing index contains", graph.GetNumRoads(), "roads,", graph.GetNumJoints(),
|
||||
"joints,", graph.GetNumPoints(), "points"));
|
||||
|
||||
FilesContainerW cont(filename, FileWriter::OP_WRITE_EXISTING);
|
||||
FileWriter writer = cont.GetWriter(ROUTING_FILE_TAG);
|
||||
|
||||
RoutingSectionHeader const routingHeader;
|
||||
routingHeader.Serialize(writer);
|
||||
graph.Serialize(writer);
|
||||
return true;
|
||||
}
|
||||
catch (RootException const & e)
|
||||
{
|
||||
LOG(LERROR, ("An exception happened while creating", ROUTING_FILE_TAG, "section:", e.what()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} // namespace routing
|
8
generator/routing_index_generator.hpp
Normal file
8
generator/routing_index_generator.hpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "std/string.hpp"
|
||||
|
||||
namespace routing
|
||||
{
|
||||
bool BuildRoutingIndex(string const & filename);
|
||||
} // namespace routing
|
|
@ -117,6 +117,7 @@ HEADERS += \
|
|||
point_to_int64.hpp \
|
||||
postcodes_matcher.hpp \ # it's in indexer due to editor wich is in indexer and depends on postcodes_marcher
|
||||
rank_table.hpp \
|
||||
routing_section.hpp \
|
||||
scale_index.hpp \
|
||||
scale_index_builder.hpp \
|
||||
scales.hpp \
|
||||
|
|
32
indexer/routing_section.hpp
Normal file
32
indexer/routing_section.hpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
|
||||
#include "coding/reader.hpp"
|
||||
#include "coding/write_to_sink.hpp"
|
||||
|
||||
#include "std/cstdint.hpp"
|
||||
|
||||
namespace feature
|
||||
{
|
||||
class RoutingSectionHeader final
|
||||
{
|
||||
public:
|
||||
RoutingSectionHeader() : m_version(0) {}
|
||||
|
||||
uint8_t GetVersion() const { return m_version; }
|
||||
|
||||
template <class Sink>
|
||||
void Serialize(Sink & sink) const
|
||||
{
|
||||
WriteToSink(sink, m_version);
|
||||
}
|
||||
|
||||
template <class Source>
|
||||
void Deserialize(Source & src)
|
||||
{
|
||||
m_version = ReadPrimitiveFromSource<decltype(m_version)>(src);
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t m_version;
|
||||
};
|
||||
} // namespace feature
|
|
@ -14,6 +14,7 @@
|
|||
#include "routing/route.hpp"
|
||||
#include "routing/routing_algorithm.hpp"
|
||||
#include "routing/routing_helpers.hpp"
|
||||
#include "routing/single_mwm_router.hpp"
|
||||
|
||||
#include "search/downloader_search_callback.hpp"
|
||||
#include "search/editor_delegate.hpp"
|
||||
|
@ -2445,7 +2446,7 @@ void Framework::SetRouterImpl(RouterType type)
|
|||
|
||||
router.reset(
|
||||
new CarRouter(m_model.GetIndex(), countryFileGetter,
|
||||
CreateCarAStarBidirectionalRouter(m_model.GetIndex(), countryFileGetter)));
|
||||
SingleMwmRouter::CreateCarRouter(m_model.GetIndex())));
|
||||
fetcher.reset(new OnlineAbsentCountriesFetcher(countryFileGetter, localFileChecker));
|
||||
m_routingSession.SetRoutingSettings(routing::GetCarRoutingSettings());
|
||||
}
|
||||
|
|
|
@ -61,13 +61,13 @@ public:
|
|||
|
||||
using TOnVisitedVertexCallback = std::function<void(TVertexType const &, TVertexType const &)>;
|
||||
|
||||
Result FindPath(TGraphType const & graph,
|
||||
Result FindPath(TGraphType & graph,
|
||||
TVertexType const & startVertex, TVertexType const & finalVertex,
|
||||
RoutingResult<TVertexType> & result,
|
||||
my::Cancellable const & cancellable = my::Cancellable(),
|
||||
TOnVisitedVertexCallback onVisitedVertexCallback = nullptr) const;
|
||||
|
||||
Result FindPathBidirectional(TGraphType const & graph,
|
||||
Result FindPathBidirectional(TGraphType & graph,
|
||||
TVertexType const & startVertex, TVertexType const & finalVertex,
|
||||
RoutingResult<TVertexType> & result,
|
||||
my::Cancellable const & cancellable = my::Cancellable(),
|
||||
|
@ -104,7 +104,7 @@ private:
|
|||
struct BidirectionalStepContext
|
||||
{
|
||||
BidirectionalStepContext(bool forward, TVertexType const & startVertex,
|
||||
TVertexType const & finalVertex, TGraphType const & graph)
|
||||
TVertexType const & finalVertex, TGraphType & graph)
|
||||
: forward(forward), startVertex(startVertex), finalVertex(finalVertex), graph(graph)
|
||||
{
|
||||
bestVertex = forward ? startVertex : finalVertex;
|
||||
|
@ -151,7 +151,7 @@ private:
|
|||
bool const forward;
|
||||
TVertexType const & startVertex;
|
||||
TVertexType const & finalVertex;
|
||||
TGraph const & graph;
|
||||
TGraph & graph;
|
||||
|
||||
priority_queue<State, vector<State>, greater<State>> queue;
|
||||
map<TVertexType, double> bestDistance;
|
||||
|
@ -182,7 +182,7 @@ private:
|
|||
|
||||
template <typename TGraph>
|
||||
typename AStarAlgorithm<TGraph>::Result AStarAlgorithm<TGraph>::FindPath(
|
||||
TGraphType const & graph,
|
||||
TGraphType & graph,
|
||||
TVertexType const & startVertex, TVertexType const & finalVertex,
|
||||
RoutingResult<TVertexType> & result,
|
||||
my::Cancellable const & cancellable,
|
||||
|
@ -257,7 +257,7 @@ typename AStarAlgorithm<TGraph>::Result AStarAlgorithm<TGraph>::FindPath(
|
|||
|
||||
template <typename TGraph>
|
||||
typename AStarAlgorithm<TGraph>::Result AStarAlgorithm<TGraph>::FindPathBidirectional(
|
||||
TGraphType const & graph,
|
||||
TGraphType & graph,
|
||||
TVertexType const & startVertex, TVertexType const & finalVertex,
|
||||
RoutingResult<TVertexType> & result,
|
||||
my::Cancellable const & cancellable,
|
||||
|
|
|
@ -244,8 +244,8 @@ bool CarRouter::CheckRoutingAbility(m2::PointD const & startPoint, m2::PointD co
|
|||
}
|
||||
|
||||
CarRouter::CarRouter(Index & index, TCountryFileFn const & countryFileFn,
|
||||
unique_ptr<IRouter> router)
|
||||
: m_index(index), m_indexManager(countryFileFn, index), m_router(move(router))
|
||||
unique_ptr<SingleMwmRouter> localRouter)
|
||||
: m_index(index), m_indexManager(countryFileFn, index), m_router(move(localRouter))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -256,11 +256,6 @@ void CarRouter::ClearState()
|
|||
m_cachedTargets.clear();
|
||||
m_cachedTargetPoint = m2::PointD::Zero();
|
||||
m_indexManager.Clear();
|
||||
|
||||
if (m_router)
|
||||
m_router->ClearState();
|
||||
else
|
||||
LOG(LERROR, ("m_router is not initialized."));
|
||||
}
|
||||
|
||||
bool CarRouter::FindRouteMSMT(TFeatureGraphNodeVec const & sources,
|
||||
|
@ -570,10 +565,11 @@ IRouter::ResultCode CarRouter::FindSingleRouteDispatcher(FeatureGraphNode const
|
|||
LOG(LERROR, ("m_router is not initialized."));
|
||||
return IRouter::InternalError;
|
||||
}
|
||||
LOG(LINFO, (m_router->GetName(), "route from", MercatorBounds::ToLatLon(source.segmentPoint), "to",
|
||||
MercatorBounds::ToLatLon(target.segmentPoint)));
|
||||
result = m_router->CalculateRoute(source.segmentPoint, m2::PointD(0, 0) /* direction */,
|
||||
target.segmentPoint, delegate, mwmRoute);
|
||||
LOG(LINFO, (m_router->GetName(), "route from", MercatorBounds::ToLatLon(source.segmentPoint),
|
||||
"to", MercatorBounds::ToLatLon(target.segmentPoint)));
|
||||
result = m_router->CalculateRoute(source.mwmId, source.segmentPoint,
|
||||
m2::PointD(0, 0) /* direction */, target.segmentPoint,
|
||||
delegate, mwmRoute);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "routing/route.hpp"
|
||||
#include "routing/router.hpp"
|
||||
#include "routing/routing_mapping.hpp"
|
||||
#include "routing/single_mwm_router.hpp"
|
||||
|
||||
#include "std/unique_ptr.hpp"
|
||||
#include "std/vector.hpp"
|
||||
|
@ -34,7 +35,7 @@ public:
|
|||
typedef vector<double> GeomTurnCandidateT;
|
||||
|
||||
CarRouter(Index & index, TCountryFileFn const & countryFileFn,
|
||||
unique_ptr<IRouter> roadGraphRouter);
|
||||
unique_ptr<SingleMwmRouter> localRouter);
|
||||
|
||||
virtual string GetName() const override;
|
||||
|
||||
|
@ -114,6 +115,6 @@ private:
|
|||
|
||||
RoutingIndexManager m_indexManager;
|
||||
|
||||
unique_ptr<IRouter> m_router;
|
||||
unique_ptr<SingleMwmRouter> m_router;
|
||||
};
|
||||
} // namespace routing
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace
|
|||
{
|
||||
/// Function to run AStar Algorithm from the base.
|
||||
IRouter::ResultCode CalculateRoute(BorderCross const & startPos, BorderCross const & finalPos,
|
||||
CrossMwmGraph const & roadGraph, RouterDelegate const & delegate,
|
||||
CrossMwmGraph & roadGraph, RouterDelegate const & delegate,
|
||||
RoutingResult<BorderCross> & route)
|
||||
{
|
||||
using TAlgorithm = AStarAlgorithm<CrossMwmGraph>;
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
namespace routing
|
||||
{
|
||||
|
||||
class IDirectionsEngine
|
||||
{
|
||||
public:
|
||||
|
@ -17,8 +16,7 @@ public:
|
|||
|
||||
virtual void Generate(IRoadGraph const & graph, vector<Junction> const & path,
|
||||
Route::TTimes & times, Route::TTurns & turns,
|
||||
vector<Junction> & routeGeometry,
|
||||
my::Cancellable const & cancellable) = 0;
|
||||
vector<Junction> & routeGeometry, my::Cancellable const & cancellable) = 0;
|
||||
|
||||
protected:
|
||||
/// \brief constructs route based on |graph| and |path|. Fills |routeEdges| with the route.
|
||||
|
@ -30,5 +28,4 @@ protected:
|
|||
void CalculateTimes(IRoadGraph const & graph, vector<Junction> const & path,
|
||||
Route::TTimes & times) const;
|
||||
};
|
||||
|
||||
} // namespace routing
|
||||
|
|
64
routing/edge_estimator.cpp
Normal file
64
routing/edge_estimator.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
#include "routing/edge_estimator.hpp"
|
||||
|
||||
#include "std/algorithm.hpp"
|
||||
|
||||
namespace routing
|
||||
{
|
||||
double constexpr kKMPH2MPS = 1000.0 / (60 * 60);
|
||||
|
||||
inline double TimeBetweenSec(m2::PointD const & from, m2::PointD const & to, double speedMPS)
|
||||
{
|
||||
ASSERT_GREATER(speedMPS, 0.0, ());
|
||||
|
||||
double const distanceM = MercatorBounds::DistanceOnEarth(from, to);
|
||||
return distanceM / speedMPS;
|
||||
}
|
||||
|
||||
class CarEdgeEstimator : public EdgeEstimator
|
||||
{
|
||||
public:
|
||||
CarEdgeEstimator(IVehicleModel const & vehicleModel);
|
||||
|
||||
// EdgeEstimator overrides:
|
||||
double CalcEdgesWeight(RoadGeometry const & road, uint32_t pointFrom,
|
||||
uint32_t pointTo) const override;
|
||||
double CalcHeuristic(m2::PointD const & from, m2::PointD const & to) const override;
|
||||
|
||||
private:
|
||||
double const m_maxSpeedMPS;
|
||||
};
|
||||
|
||||
CarEdgeEstimator::CarEdgeEstimator(IVehicleModel const & vehicleModel)
|
||||
: m_maxSpeedMPS(vehicleModel.GetMaxSpeed() * kKMPH2MPS)
|
||||
{
|
||||
}
|
||||
|
||||
double CarEdgeEstimator::CalcEdgesWeight(RoadGeometry const & road, uint32_t pointFrom,
|
||||
uint32_t pointTo) const
|
||||
{
|
||||
uint32_t const start = min(pointFrom, pointTo);
|
||||
uint32_t const finish = max(pointFrom, pointTo);
|
||||
ASSERT_LESS(finish, road.GetPointsCount(), ());
|
||||
|
||||
double result = 0.0;
|
||||
double const speedMPS = road.GetSpeed() * kKMPH2MPS;
|
||||
for (uint32_t i = start; i < finish; ++i)
|
||||
result += TimeBetweenSec(road.GetPoint(i), road.GetPoint(i + 1), speedMPS);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
double CarEdgeEstimator::CalcHeuristic(m2::PointD const & from, m2::PointD const & to) const
|
||||
{
|
||||
return TimeBetweenSec(from, to, m_maxSpeedMPS);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace routing
|
||||
{
|
||||
// static
|
||||
shared_ptr<EdgeEstimator> EdgeEstimator::CreateForCar(IVehicleModel const & vehicleModel)
|
||||
{
|
||||
return make_shared<CarEdgeEstimator>(vehicleModel);
|
||||
}
|
||||
} // namespace routing
|
24
routing/edge_estimator.hpp
Normal file
24
routing/edge_estimator.hpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include "routing/geometry.hpp"
|
||||
#include "routing/vehicle_model.hpp"
|
||||
|
||||
#include "geometry/point2d.hpp"
|
||||
|
||||
#include "std/cstdint.hpp"
|
||||
#include "std/shared_ptr.hpp"
|
||||
|
||||
namespace routing
|
||||
{
|
||||
class EdgeEstimator
|
||||
{
|
||||
public:
|
||||
virtual ~EdgeEstimator() = default;
|
||||
|
||||
virtual double CalcEdgesWeight(RoadGeometry const & road, uint32_t pointFrom,
|
||||
uint32_t pointTo) const = 0;
|
||||
virtual double CalcHeuristic(m2::PointD const & from, m2::PointD const & to) const = 0;
|
||||
|
||||
static shared_ptr<EdgeEstimator> CreateForCar(IVehicleModel const & vehicleModel);
|
||||
};
|
||||
} // namespace routing
|
|
@ -47,8 +47,8 @@ FeaturesRoadGraph::Value::Value(MwmSet::MwmHandle handle) : m_mwmHandle(move(han
|
|||
}
|
||||
|
||||
FeaturesRoadGraph::CrossCountryVehicleModel::CrossCountryVehicleModel(
|
||||
unique_ptr<VehicleModelFactory> vehicleModelFactory)
|
||||
: m_vehicleModelFactory(move(vehicleModelFactory))
|
||||
shared_ptr<VehicleModelFactory> vehicleModelFactory)
|
||||
: m_vehicleModelFactory(vehicleModelFactory)
|
||||
, m_maxSpeedKMPH(m_vehicleModelFactory->GetVehicleModel()->GetMaxSpeed())
|
||||
{
|
||||
}
|
||||
|
@ -108,8 +108,8 @@ void FeaturesRoadGraph::RoadInfoCache::Clear()
|
|||
m_cache.clear();
|
||||
}
|
||||
FeaturesRoadGraph::FeaturesRoadGraph(Index const & index, IRoadGraph::Mode mode,
|
||||
unique_ptr<VehicleModelFactory> vehicleModelFactory)
|
||||
: m_index(index), m_mode(mode), m_vehicleModel(move(vehicleModelFactory))
|
||||
shared_ptr<VehicleModelFactory> vehicleModelFactory)
|
||||
: m_index(index), m_mode(mode), m_vehicleModel(vehicleModelFactory)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ private:
|
|||
class CrossCountryVehicleModel : public IVehicleModel
|
||||
{
|
||||
public:
|
||||
CrossCountryVehicleModel(unique_ptr<VehicleModelFactory> vehicleModelFactory);
|
||||
CrossCountryVehicleModel(shared_ptr<VehicleModelFactory> vehicleModelFactory);
|
||||
|
||||
// IVehicleModel overrides:
|
||||
double GetSpeed(FeatureType const & f) const override;
|
||||
|
@ -39,7 +39,7 @@ private:
|
|||
private:
|
||||
IVehicleModel * GetVehicleModel(FeatureID const & featureId) const;
|
||||
|
||||
unique_ptr<VehicleModelFactory> const m_vehicleModelFactory;
|
||||
shared_ptr<VehicleModelFactory> const m_vehicleModelFactory;
|
||||
double const m_maxSpeedKMPH;
|
||||
|
||||
mutable map<MwmSet::MwmId, shared_ptr<IVehicleModel>> m_cache;
|
||||
|
@ -59,7 +59,7 @@ private:
|
|||
|
||||
public:
|
||||
FeaturesRoadGraph(Index const & index, IRoadGraph::Mode mode,
|
||||
unique_ptr<VehicleModelFactory> vehicleModelFactory);
|
||||
shared_ptr<VehicleModelFactory> vehicleModelFactory);
|
||||
|
||||
static uint32_t GetStreetReadScale();
|
||||
|
||||
|
|
96
routing/geometry.cpp
Normal file
96
routing/geometry.cpp
Normal file
|
@ -0,0 +1,96 @@
|
|||
#include "routing/geometry.hpp"
|
||||
|
||||
#include "routing/routing_exception.hpp"
|
||||
|
||||
#include "geometry/mercator.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
|
||||
#include "std/string.hpp"
|
||||
|
||||
using namespace routing;
|
||||
|
||||
namespace
|
||||
{
|
||||
class GeometryLoaderImpl final : public GeometryLoader
|
||||
{
|
||||
public:
|
||||
GeometryLoaderImpl(Index const & index, MwmSet::MwmId const & mwmId, string const & country,
|
||||
shared_ptr<IVehicleModel> vehicleModel);
|
||||
|
||||
// GeometryLoader overrides:
|
||||
virtual void Load(uint32_t featureId, RoadGeometry & road) const override;
|
||||
|
||||
private:
|
||||
shared_ptr<IVehicleModel> m_vehicleModel;
|
||||
Index::FeaturesLoaderGuard m_guard;
|
||||
string const m_country;
|
||||
};
|
||||
|
||||
GeometryLoaderImpl::GeometryLoaderImpl(Index const & index, MwmSet::MwmId const & mwmId,
|
||||
string const & country,
|
||||
shared_ptr<IVehicleModel> vehicleModel)
|
||||
: m_vehicleModel(vehicleModel), m_guard(index, mwmId), m_country(country)
|
||||
{
|
||||
ASSERT(m_vehicleModel, ());
|
||||
}
|
||||
|
||||
void GeometryLoaderImpl::Load(uint32_t featureId, RoadGeometry & road) const
|
||||
{
|
||||
FeatureType feature;
|
||||
bool const isFound = m_guard.GetFeatureByIndex(featureId, feature);
|
||||
if (!isFound)
|
||||
MYTHROW(RoutingException, ("Feature", featureId, "not found in ", m_country));
|
||||
|
||||
feature.ParseGeometry(FeatureType::BEST_GEOMETRY);
|
||||
road.Load(*m_vehicleModel, feature);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace routing
|
||||
{
|
||||
// RoadGeometry ------------------------------------------------------------------------------------
|
||||
RoadGeometry::RoadGeometry(bool oneWay, double speed, Points const & points)
|
||||
: m_points(points), m_speed(speed), m_isRoad(true), m_isOneWay(oneWay)
|
||||
{
|
||||
ASSERT_GREATER(speed, 0.0, ());
|
||||
}
|
||||
|
||||
void RoadGeometry::Load(IVehicleModel const & vehicleModel, FeatureType const & feature)
|
||||
{
|
||||
m_isRoad = vehicleModel.IsRoad(feature);
|
||||
m_isOneWay = vehicleModel.IsOneWay(feature);
|
||||
m_speed = vehicleModel.GetSpeed(feature);
|
||||
|
||||
m_points.clear();
|
||||
m_points.reserve(feature.GetPointsCount());
|
||||
for (size_t i = 0; i < feature.GetPointsCount(); ++i)
|
||||
m_points.emplace_back(feature.GetPoint(i));
|
||||
}
|
||||
|
||||
// Geometry ----------------------------------------------------------------------------------------
|
||||
Geometry::Geometry(unique_ptr<GeometryLoader> loader) : m_loader(move(loader))
|
||||
{
|
||||
ASSERT(m_loader, ());
|
||||
}
|
||||
|
||||
RoadGeometry const & Geometry::GetRoad(uint32_t featureId)
|
||||
{
|
||||
auto const & it = m_roads.find(featureId);
|
||||
if (it != m_roads.cend())
|
||||
return it->second;
|
||||
|
||||
RoadGeometry & road = m_roads[featureId];
|
||||
m_loader->Load(featureId, road);
|
||||
return road;
|
||||
}
|
||||
|
||||
// static
|
||||
unique_ptr<GeometryLoader> GeometryLoader::Create(Index const & index, MwmSet::MwmId const & mwmId,
|
||||
shared_ptr<IVehicleModel> vehicleModel)
|
||||
{
|
||||
CHECK(mwmId.IsAlive(), ());
|
||||
return make_unique<GeometryLoaderImpl>(index, mwmId, mwmId.GetInfo()->GetCountryName(),
|
||||
vehicleModel);
|
||||
}
|
||||
} // namespace routing
|
80
routing/geometry.hpp
Normal file
80
routing/geometry.hpp
Normal file
|
@ -0,0 +1,80 @@
|
|||
#pragma once
|
||||
|
||||
#include "routing/road_point.hpp"
|
||||
#include "routing/vehicle_model.hpp"
|
||||
|
||||
#include "indexer/index.hpp"
|
||||
|
||||
#include "geometry/point2d.hpp"
|
||||
|
||||
#include "base/buffer_vector.hpp"
|
||||
|
||||
#include "std/cstdint.hpp"
|
||||
#include "std/shared_ptr.hpp"
|
||||
#include "std/unique_ptr.hpp"
|
||||
|
||||
namespace routing
|
||||
{
|
||||
class RoadGeometry final
|
||||
{
|
||||
public:
|
||||
using Points = buffer_vector<m2::PointD, 32>;
|
||||
|
||||
RoadGeometry() = default;
|
||||
RoadGeometry(bool oneWay, double speed, Points const & points);
|
||||
|
||||
void Load(IVehicleModel const & vehicleModel, FeatureType const & feature);
|
||||
|
||||
bool IsRoad() const { return m_isRoad; }
|
||||
|
||||
bool IsOneWay() const { return m_isOneWay; }
|
||||
|
||||
// Kilometers per hour.
|
||||
double GetSpeed() const { return m_speed; }
|
||||
|
||||
m2::PointD const & GetPoint(uint32_t pointId) const
|
||||
{
|
||||
ASSERT_LESS(pointId, m_points.size(), ());
|
||||
return m_points[pointId];
|
||||
}
|
||||
|
||||
uint32_t GetPointsCount() const { return m_points.size(); }
|
||||
|
||||
private:
|
||||
Points m_points;
|
||||
double m_speed = 0.0;
|
||||
bool m_isRoad = false;
|
||||
bool m_isOneWay = false;
|
||||
};
|
||||
|
||||
class GeometryLoader
|
||||
{
|
||||
public:
|
||||
virtual ~GeometryLoader() = default;
|
||||
|
||||
virtual void Load(uint32_t featureId, RoadGeometry & road) const = 0;
|
||||
|
||||
// mwmId should be alive: it is caller responsibility to check it.
|
||||
static unique_ptr<GeometryLoader> Create(Index const & index, MwmSet::MwmId const & mwmId,
|
||||
shared_ptr<IVehicleModel> vehicleModel);
|
||||
};
|
||||
|
||||
class Geometry final
|
||||
{
|
||||
public:
|
||||
Geometry() = default;
|
||||
explicit Geometry(unique_ptr<GeometryLoader> loader);
|
||||
|
||||
RoadGeometry const & GetRoad(uint32_t featureId);
|
||||
|
||||
m2::PointD const & GetPoint(RoadPoint const & rp)
|
||||
{
|
||||
return GetRoad(rp.GetFeatureId()).GetPoint(rp.GetPointId());
|
||||
}
|
||||
|
||||
private:
|
||||
// Feature id to RoadGeometry map.
|
||||
unordered_map<uint32_t, RoadGeometry> m_roads;
|
||||
unique_ptr<GeometryLoader> m_loader;
|
||||
};
|
||||
} // namespace routing
|
93
routing/index_graph.cpp
Normal file
93
routing/index_graph.cpp
Normal file
|
@ -0,0 +1,93 @@
|
|||
#include "index_graph.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
#include "base/exception.hpp"
|
||||
|
||||
namespace routing
|
||||
{
|
||||
IndexGraph::IndexGraph(unique_ptr<GeometryLoader> loader, shared_ptr<EdgeEstimator> estimator)
|
||||
: m_geometry(move(loader)), m_estimator(move(estimator))
|
||||
{
|
||||
ASSERT(m_estimator, ());
|
||||
}
|
||||
|
||||
void IndexGraph::GetEdgeList(Joint::Id jointId, bool isOutgoing, vector<JointEdge> & edges)
|
||||
{
|
||||
m_jointIndex.ForEachPoint(jointId, [this, &edges, isOutgoing](RoadPoint const & rp) {
|
||||
GetNeighboringEdges(rp, isOutgoing, edges);
|
||||
});
|
||||
}
|
||||
|
||||
m2::PointD const & IndexGraph::GetPoint(Joint::Id jointId)
|
||||
{
|
||||
return m_geometry.GetPoint(m_jointIndex.GetPoint(jointId));
|
||||
}
|
||||
|
||||
void IndexGraph::Import(vector<Joint> const & joints)
|
||||
{
|
||||
m_roadIndex.Import(joints);
|
||||
m_jointIndex.Build(m_roadIndex, joints.size());
|
||||
}
|
||||
|
||||
Joint::Id IndexGraph::InsertJoint(RoadPoint const & rp)
|
||||
{
|
||||
Joint::Id const existId = m_roadIndex.GetJointId(rp);
|
||||
if (existId != Joint::kInvalidId)
|
||||
return existId;
|
||||
|
||||
Joint::Id const jointId = m_jointIndex.InsertJoint(rp);
|
||||
m_roadIndex.AddJoint(rp, jointId);
|
||||
return jointId;
|
||||
}
|
||||
|
||||
bool IndexGraph::JointLiesOnRoad(Joint::Id jointId, uint32_t featureId) const
|
||||
{
|
||||
bool result = false;
|
||||
m_jointIndex.ForEachPoint(jointId, [&result, featureId](RoadPoint const & rp) {
|
||||
if (rp.GetFeatureId() == featureId)
|
||||
result = true;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void IndexGraph::GetNeighboringEdges(RoadPoint const & rp, bool isOutgoing,
|
||||
vector<JointEdge> & edges)
|
||||
{
|
||||
RoadGeometry const & road = m_geometry.GetRoad(rp.GetFeatureId());
|
||||
if (!road.IsRoad())
|
||||
return;
|
||||
|
||||
bool const bidirectional = !road.IsOneWay();
|
||||
if (!isOutgoing || bidirectional)
|
||||
GetNeighboringEdge(road, rp, false /* forward */, edges);
|
||||
|
||||
if (isOutgoing || bidirectional)
|
||||
GetNeighboringEdge(road, rp, true /* forward */, edges);
|
||||
}
|
||||
|
||||
inline void IndexGraph::GetNeighboringEdge(RoadGeometry const & road, RoadPoint const & rp,
|
||||
bool forward, vector<JointEdge> & edges) const
|
||||
{
|
||||
pair<Joint::Id, uint32_t> const & neighbor = m_roadIndex.FindNeighbor(rp, forward);
|
||||
if (neighbor.first != Joint::kInvalidId)
|
||||
{
|
||||
double const distance = m_estimator->CalcEdgesWeight(road, rp.GetPointId(), neighbor.second);
|
||||
edges.push_back({neighbor.first, distance});
|
||||
}
|
||||
}
|
||||
|
||||
void IndexGraph::GetDirectedEdge(uint32_t featureId, uint32_t pointFrom, uint32_t pointTo,
|
||||
Joint::Id target, bool forward, vector<JointEdge> & edges)
|
||||
{
|
||||
RoadGeometry const & road = m_geometry.GetRoad(featureId);
|
||||
if (!road.IsRoad())
|
||||
return;
|
||||
|
||||
if (road.IsOneWay() && forward != (pointFrom < pointTo))
|
||||
return;
|
||||
|
||||
double const distance = m_estimator->CalcEdgesWeight(road, pointFrom, pointTo);
|
||||
edges.emplace_back(target, distance);
|
||||
}
|
||||
} // namespace routing
|
92
routing/index_graph.hpp
Normal file
92
routing/index_graph.hpp
Normal file
|
@ -0,0 +1,92 @@
|
|||
#pragma once
|
||||
|
||||
#include "routing/edge_estimator.hpp"
|
||||
#include "routing/geometry.hpp"
|
||||
#include "routing/joint.hpp"
|
||||
#include "routing/joint_index.hpp"
|
||||
#include "routing/road_index.hpp"
|
||||
#include "routing/road_point.hpp"
|
||||
|
||||
#include "coding/reader.hpp"
|
||||
#include "coding/write_to_sink.hpp"
|
||||
|
||||
#include "geometry/point2d.hpp"
|
||||
|
||||
#include "std/cstdint.hpp"
|
||||
#include "std/shared_ptr.hpp"
|
||||
#include "std/unique_ptr.hpp"
|
||||
#include "std/utility.hpp"
|
||||
#include "std/vector.hpp"
|
||||
|
||||
namespace routing
|
||||
{
|
||||
class JointEdge final
|
||||
{
|
||||
public:
|
||||
JointEdge(Joint::Id target, double weight) : m_target(target), m_weight(weight) {}
|
||||
Joint::Id GetTarget() const { return m_target; }
|
||||
double GetWeight() const { return m_weight; }
|
||||
|
||||
private:
|
||||
// Target is vertex going to for outgoing edges, vertex going from for ingoing edges.
|
||||
Joint::Id const m_target;
|
||||
double const m_weight;
|
||||
};
|
||||
|
||||
class IndexGraph final
|
||||
{
|
||||
public:
|
||||
IndexGraph() = default;
|
||||
explicit IndexGraph(unique_ptr<GeometryLoader> loader, shared_ptr<EdgeEstimator> estimator);
|
||||
|
||||
// Creates edge for points in same feature.
|
||||
void GetDirectedEdge(uint32_t featureId, uint32_t pointFrom, uint32_t pointTo, Joint::Id target,
|
||||
bool forward, vector<JointEdge> & edges);
|
||||
void GetNeighboringEdges(RoadPoint const & rp, bool isOutgoing, vector<JointEdge> & edges);
|
||||
|
||||
// Put outgoing (or ingoing) egdes for jointId to the 'edges' vector.
|
||||
void GetEdgeList(Joint::Id jointId, bool isOutgoing, vector<JointEdge> & edges);
|
||||
Joint::Id GetJointId(RoadPoint const & rp) const { return m_roadIndex.GetJointId(rp); }
|
||||
m2::PointD const & GetPoint(Joint::Id jointId);
|
||||
|
||||
Geometry & GetGeometry() { return m_geometry; }
|
||||
EdgeEstimator const & GetEstimator() const { return *m_estimator; }
|
||||
uint32_t GetNumRoads() const { return m_roadIndex.GetSize(); }
|
||||
uint32_t GetNumJoints() const { return m_jointIndex.GetNumJoints(); }
|
||||
uint32_t GetNumPoints() const { return m_jointIndex.GetNumPoints(); }
|
||||
|
||||
void Import(vector<Joint> const & joints);
|
||||
Joint::Id InsertJoint(RoadPoint const & rp);
|
||||
bool JointLiesOnRoad(Joint::Id jointId, uint32_t featureId) const;
|
||||
|
||||
template <typename F>
|
||||
void ForEachPoint(Joint::Id jointId, F && f) const
|
||||
{
|
||||
m_jointIndex.ForEachPoint(jointId, forward<F>(f));
|
||||
}
|
||||
|
||||
template <class Sink>
|
||||
void Serialize(Sink & sink) const
|
||||
{
|
||||
WriteToSink(sink, static_cast<uint32_t>(GetNumJoints()));
|
||||
m_roadIndex.Serialize(sink);
|
||||
}
|
||||
|
||||
template <class Source>
|
||||
void Deserialize(Source & src)
|
||||
{
|
||||
uint32_t const jointsSize = ReadPrimitiveFromSource<uint32_t>(src);
|
||||
m_roadIndex.Deserialize(src);
|
||||
m_jointIndex.Build(m_roadIndex, jointsSize);
|
||||
}
|
||||
|
||||
private:
|
||||
void GetNeighboringEdge(RoadGeometry const & road, RoadPoint const & rp, bool forward,
|
||||
vector<JointEdge> & edges) const;
|
||||
|
||||
Geometry m_geometry;
|
||||
shared_ptr<EdgeEstimator> m_estimator;
|
||||
RoadIndex m_roadIndex;
|
||||
JointIndex m_jointIndex;
|
||||
};
|
||||
} // namespace routing
|
195
routing/index_graph_starter.cpp
Normal file
195
routing/index_graph_starter.cpp
Normal file
|
@ -0,0 +1,195 @@
|
|||
#include "routing/index_graph_starter.hpp"
|
||||
|
||||
#include "routing/routing_exception.hpp"
|
||||
|
||||
namespace routing
|
||||
{
|
||||
IndexGraphStarter::IndexGraphStarter(IndexGraph & graph, RoadPoint const & startPoint,
|
||||
RoadPoint const & finishPoint)
|
||||
: m_graph(graph)
|
||||
, m_start(graph, startPoint, graph.GetNumJoints())
|
||||
, m_finish(graph, finishPoint, graph.GetNumJoints() + 1)
|
||||
{
|
||||
m_start.SetupJointId(graph);
|
||||
|
||||
if (startPoint == finishPoint)
|
||||
m_finish.m_jointId = m_start.m_jointId;
|
||||
else
|
||||
m_finish.SetupJointId(graph);
|
||||
}
|
||||
|
||||
m2::PointD const & IndexGraphStarter::GetPoint(Joint::Id jointId)
|
||||
{
|
||||
if (jointId == m_start.m_fakeId)
|
||||
return m_graph.GetGeometry().GetPoint(m_start.m_point);
|
||||
|
||||
if (jointId == m_finish.m_fakeId)
|
||||
return m_graph.GetGeometry().GetPoint(m_finish.m_point);
|
||||
|
||||
return m_graph.GetPoint(jointId);
|
||||
}
|
||||
|
||||
void IndexGraphStarter::RedressRoute(vector<Joint::Id> const & route,
|
||||
vector<RoadPoint> & roadPoints)
|
||||
{
|
||||
if (route.size() < 2)
|
||||
{
|
||||
if (route.size() == 1)
|
||||
roadPoints.emplace_back(m_start.m_point);
|
||||
return;
|
||||
}
|
||||
|
||||
roadPoints.reserve(route.size() * 2);
|
||||
|
||||
for (size_t i = 0; i < route.size() - 1; ++i)
|
||||
{
|
||||
Joint::Id const prevJoint = route[i];
|
||||
Joint::Id const nextJoint = route[i + 1];
|
||||
|
||||
RoadPoint rp0;
|
||||
RoadPoint rp1;
|
||||
FindPointsWithCommonFeature(prevJoint, nextJoint, rp0, rp1);
|
||||
if (i == 0)
|
||||
roadPoints.emplace_back(rp0);
|
||||
|
||||
uint32_t const featureId = rp0.GetFeatureId();
|
||||
uint32_t const pointFrom = rp0.GetPointId();
|
||||
uint32_t const pointTo = rp1.GetPointId();
|
||||
|
||||
if (pointFrom < pointTo)
|
||||
{
|
||||
for (uint32_t pointId = pointFrom + 1; pointId < pointTo; ++pointId)
|
||||
roadPoints.emplace_back(featureId, pointId);
|
||||
}
|
||||
else if (pointFrom > pointTo)
|
||||
{
|
||||
for (uint32_t pointId = pointFrom - 1; pointId > pointTo; --pointId)
|
||||
roadPoints.emplace_back(featureId, pointId);
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK(false,
|
||||
("Wrong equality pointFrom = pointTo =", pointFrom, ", featureId = ", featureId));
|
||||
}
|
||||
|
||||
roadPoints.emplace_back(rp1);
|
||||
}
|
||||
}
|
||||
|
||||
void IndexGraphStarter::GetEdgesList(Joint::Id jointId, bool isOutgoing, vector<JointEdge> & edges)
|
||||
{
|
||||
edges.clear();
|
||||
|
||||
if (jointId == m_start.m_fakeId)
|
||||
{
|
||||
GetFakeEdges(m_start, m_finish, isOutgoing, edges);
|
||||
return;
|
||||
}
|
||||
|
||||
if (jointId == m_finish.m_fakeId)
|
||||
{
|
||||
GetFakeEdges(m_finish, m_start, isOutgoing, edges);
|
||||
return;
|
||||
}
|
||||
|
||||
m_graph.GetEdgeList(jointId, isOutgoing, edges);
|
||||
GetArrivalFakeEdges(jointId, m_start, isOutgoing, edges);
|
||||
GetArrivalFakeEdges(jointId, m_finish, isOutgoing, edges);
|
||||
}
|
||||
|
||||
void IndexGraphStarter::GetFakeEdges(IndexGraphStarter::FakeJoint const & from,
|
||||
IndexGraphStarter::FakeJoint const & to, bool isOutgoing,
|
||||
vector<JointEdge> & edges)
|
||||
{
|
||||
m_graph.GetNeighboringEdges(from.m_point, isOutgoing, edges);
|
||||
|
||||
if (!to.BelongsToGraph() && from.m_point.GetFeatureId() == to.m_point.GetFeatureId())
|
||||
{
|
||||
m_graph.GetDirectedEdge(from.m_point.GetFeatureId(), from.m_point.GetPointId(),
|
||||
to.m_point.GetPointId(), to.m_jointId, isOutgoing, edges);
|
||||
}
|
||||
}
|
||||
|
||||
void IndexGraphStarter::GetArrivalFakeEdges(Joint::Id jointId,
|
||||
IndexGraphStarter::FakeJoint const & fakeJoint,
|
||||
bool isOutgoing, vector<JointEdge> & edges)
|
||||
{
|
||||
if (fakeJoint.BelongsToGraph())
|
||||
return;
|
||||
|
||||
if (!m_graph.JointLiesOnRoad(jointId, fakeJoint.m_point.GetFeatureId()))
|
||||
return;
|
||||
|
||||
vector<JointEdge> startEdges;
|
||||
m_graph.GetNeighboringEdges(fakeJoint.m_point, !isOutgoing, startEdges);
|
||||
for (JointEdge const & edge : startEdges)
|
||||
{
|
||||
if (edge.GetTarget() == jointId)
|
||||
edges.emplace_back(fakeJoint.m_jointId, edge.GetWeight());
|
||||
}
|
||||
}
|
||||
|
||||
void IndexGraphStarter::FindPointsWithCommonFeature(Joint::Id jointId0, Joint::Id jointId1,
|
||||
RoadPoint & result0, RoadPoint & result1)
|
||||
{
|
||||
bool found = false;
|
||||
double minWeight = -1.0;
|
||||
|
||||
ForEachPoint(jointId0, [&](RoadPoint const & rp0) {
|
||||
ForEachPoint(jointId1, [&](RoadPoint const & rp1) {
|
||||
if (rp0.GetFeatureId() != rp1.GetFeatureId())
|
||||
return;
|
||||
|
||||
RoadGeometry const & road = m_graph.GetGeometry().GetRoad(rp0.GetFeatureId());
|
||||
if (!road.IsRoad())
|
||||
return;
|
||||
|
||||
if (road.IsOneWay() && rp0.GetPointId() > rp1.GetPointId())
|
||||
return;
|
||||
|
||||
if (found)
|
||||
{
|
||||
if (minWeight < 0.0)
|
||||
{
|
||||
// CalcEdgesWeight is very expensive.
|
||||
// So calculate it only if second common feature found.
|
||||
RoadGeometry const & prevRoad = m_graph.GetGeometry().GetRoad(result0.GetFeatureId());
|
||||
minWeight = m_graph.GetEstimator().CalcEdgesWeight(prevRoad, result0.GetPointId(),
|
||||
result1.GetPointId());
|
||||
}
|
||||
|
||||
double const weight =
|
||||
m_graph.GetEstimator().CalcEdgesWeight(road, rp0.GetPointId(), rp1.GetPointId());
|
||||
if (weight < minWeight)
|
||||
{
|
||||
minWeight = weight;
|
||||
result0 = rp0;
|
||||
result1 = rp1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result0 = rp0;
|
||||
result1 = rp1;
|
||||
found = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
CHECK(found, ("Can't find common feature for joints", jointId0, jointId1));
|
||||
}
|
||||
|
||||
// IndexGraphStarter::FakeJoint --------------------------------------------------------------------
|
||||
IndexGraphStarter::FakeJoint::FakeJoint(IndexGraph const & graph, RoadPoint const & point,
|
||||
Joint::Id fakeId)
|
||||
: m_point(point), m_fakeId(fakeId), m_jointId(Joint::kInvalidId)
|
||||
{
|
||||
}
|
||||
|
||||
void IndexGraphStarter::FakeJoint::SetupJointId(IndexGraph const & graph)
|
||||
{
|
||||
m_jointId = graph.GetJointId(m_point);
|
||||
if (m_jointId == Joint::kInvalidId)
|
||||
m_jointId = m_fakeId;
|
||||
}
|
||||
} // namespace routing
|
98
routing/index_graph_starter.hpp
Normal file
98
routing/index_graph_starter.hpp
Normal file
|
@ -0,0 +1,98 @@
|
|||
#pragma once
|
||||
|
||||
#include "routing/index_graph.hpp"
|
||||
#include "routing/joint.hpp"
|
||||
|
||||
#include "std/utility.hpp"
|
||||
|
||||
namespace routing
|
||||
{
|
||||
// The problem:
|
||||
// IndexGraph contains only road points connected in joints.
|
||||
// So it is possible IndexGraph doesn't contain start and finish.
|
||||
//
|
||||
// IndexGraphStarter adds fake start and finish joint ids for AStarAlgorithm.
|
||||
//
|
||||
class IndexGraphStarter final
|
||||
{
|
||||
public:
|
||||
// AStarAlgorithm types aliases:
|
||||
using TVertexType = Joint::Id;
|
||||
using TEdgeType = JointEdge;
|
||||
|
||||
IndexGraphStarter(IndexGraph & graph, RoadPoint const & startPoint,
|
||||
RoadPoint const & finishPoint);
|
||||
|
||||
IndexGraph & GetGraph() const { return m_graph; }
|
||||
Joint::Id GetStartJoint() const { return m_start.m_jointId; }
|
||||
Joint::Id GetFinishJoint() const { return m_finish.m_jointId; }
|
||||
|
||||
m2::PointD const & GetPoint(Joint::Id jointId);
|
||||
|
||||
void GetOutgoingEdgesList(Joint::Id jointId, vector<JointEdge> & edges)
|
||||
{
|
||||
GetEdgesList(jointId, true /* isOutgoing */, edges);
|
||||
}
|
||||
|
||||
void GetIngoingEdgesList(Joint::Id jointId, vector<JointEdge> & edges)
|
||||
{
|
||||
GetEdgesList(jointId, false /* isOutgoing */, edges);
|
||||
}
|
||||
|
||||
double HeuristicCostEstimate(Joint::Id from, Joint::Id to)
|
||||
{
|
||||
return m_graph.GetEstimator().CalcHeuristic(GetPoint(from), GetPoint(to));
|
||||
}
|
||||
|
||||
// Add intermediate points to route (those don't correspond to any joint).
|
||||
//
|
||||
// Also convert joint ids to RoadPoints.
|
||||
void RedressRoute(vector<Joint::Id> const & route, vector<RoadPoint> & roadPoints);
|
||||
|
||||
private:
|
||||
struct FakeJoint final
|
||||
{
|
||||
FakeJoint(IndexGraph const & graph, RoadPoint const & point, Joint::Id fakeId);
|
||||
|
||||
void SetupJointId(IndexGraph const & graph);
|
||||
bool BelongsToGraph() const { return m_jointId != m_fakeId; }
|
||||
|
||||
RoadPoint const m_point;
|
||||
Joint::Id const m_fakeId;
|
||||
Joint::Id m_jointId;
|
||||
};
|
||||
|
||||
template <typename F>
|
||||
void ForEachPoint(Joint::Id jointId, F && f) const
|
||||
{
|
||||
if (jointId == m_start.m_fakeId)
|
||||
{
|
||||
f(m_start.m_point);
|
||||
return;
|
||||
}
|
||||
|
||||
if (jointId == m_finish.m_fakeId)
|
||||
{
|
||||
f(m_finish.m_point);
|
||||
return;
|
||||
}
|
||||
|
||||
m_graph.ForEachPoint(jointId, forward<F>(f));
|
||||
}
|
||||
|
||||
void GetEdgesList(Joint::Id jointId, bool isOutgoing, vector<JointEdge> & edges);
|
||||
void GetFakeEdges(FakeJoint const & from, FakeJoint const & to, bool isOutgoing,
|
||||
vector<JointEdge> & edges);
|
||||
void GetArrivalFakeEdges(Joint::Id jointId, FakeJoint const & fakeJoint, bool isOutgoing,
|
||||
vector<JointEdge> & edges);
|
||||
|
||||
// Find two road points lying on the same feature.
|
||||
// If there are several pairs of such points, return pair with minimal distance.
|
||||
void FindPointsWithCommonFeature(Joint::Id jointId0, Joint::Id jointId1, RoadPoint & result0,
|
||||
RoadPoint & result1);
|
||||
|
||||
IndexGraph & m_graph;
|
||||
FakeJoint m_start;
|
||||
FakeJoint m_finish;
|
||||
};
|
||||
} // namespace routing
|
7
routing/joint.cpp
Normal file
7
routing/joint.cpp
Normal file
|
@ -0,0 +1,7 @@
|
|||
#include "routing/joint.hpp"
|
||||
|
||||
namespace routing
|
||||
{
|
||||
// static
|
||||
Joint::Id constexpr Joint::kInvalidId;
|
||||
} // namespace routing
|
29
routing/joint.hpp
Normal file
29
routing/joint.hpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
|
||||
#include "routing/road_point.hpp"
|
||||
|
||||
#include "base/buffer_vector.hpp"
|
||||
|
||||
#include "std/cstdint.hpp"
|
||||
#include "std/limits.hpp"
|
||||
|
||||
namespace routing
|
||||
{
|
||||
// Joint represents roads connection.
|
||||
// It contains RoadPoint for each connected road.
|
||||
class Joint final
|
||||
{
|
||||
public:
|
||||
using Id = uint32_t;
|
||||
static Id constexpr kInvalidId = numeric_limits<Id>::max();
|
||||
|
||||
void AddPoint(RoadPoint const & rp) { m_points.emplace_back(rp); }
|
||||
|
||||
size_t GetSize() const { return m_points.size(); }
|
||||
|
||||
RoadPoint const & GetEntry(size_t i) const { return m_points[i]; }
|
||||
|
||||
private:
|
||||
buffer_vector<RoadPoint, 2> m_points;
|
||||
};
|
||||
} // namespace routing
|
61
routing/joint_index.cpp
Normal file
61
routing/joint_index.cpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
#include "routing/joint_index.hpp"
|
||||
|
||||
#include "routing/routing_exception.hpp"
|
||||
|
||||
namespace routing
|
||||
{
|
||||
Joint::Id JointIndex::InsertJoint(RoadPoint const & rp)
|
||||
{
|
||||
Joint::Id const jointId = GetNumJoints();
|
||||
m_points.emplace_back(rp);
|
||||
m_offsets.emplace_back(m_points.size());
|
||||
return jointId;
|
||||
}
|
||||
|
||||
void JointIndex::AppendToJoint(Joint::Id jointId, RoadPoint const & rp)
|
||||
{
|
||||
m_dynamicJoints[jointId].AddPoint(rp);
|
||||
}
|
||||
|
||||
void JointIndex::Build(RoadIndex const & roadIndex, uint32_t numJoints)
|
||||
{
|
||||
m_dynamicJoints.clear();
|
||||
|
||||
// + 1 is protection for 'End' method from out of bounds.
|
||||
// Call End(numJoints-1) requires more size, so add one more item.
|
||||
// Therefore m_offsets.size() == numJoints + 1,
|
||||
// And m_offsets.back() == m_points.size()
|
||||
m_offsets.assign(numJoints + 1, 0);
|
||||
|
||||
// Calculate sizes.
|
||||
// Example for numJoints = 6:
|
||||
// 2, 5, 3, 4, 2, 3, 0
|
||||
roadIndex.ForEachRoad([this, numJoints](uint32_t /* featureId */, RoadJointIds const & road) {
|
||||
road.ForEachJoint([this, numJoints](uint32_t /* pointId */, Joint::Id jointId) {
|
||||
ASSERT_LESS(jointId, numJoints, ());
|
||||
++m_offsets[jointId];
|
||||
});
|
||||
});
|
||||
|
||||
// Fill offsets with end bounds.
|
||||
// Example: 2, 7, 10, 14, 16, 19, 19
|
||||
for (size_t i = 1; i < m_offsets.size(); ++i)
|
||||
m_offsets[i] += m_offsets[i - 1];
|
||||
|
||||
m_points.resize(m_offsets.back());
|
||||
|
||||
// Now fill points.
|
||||
// Offsets after this operation are begin bounds:
|
||||
// 0, 2, 7, 10, 14, 16, 19
|
||||
roadIndex.ForEachRoad([this](uint32_t featureId, RoadJointIds const & road) {
|
||||
road.ForEachJoint([this, featureId](uint32_t pointId, Joint::Id jointId) {
|
||||
uint32_t & offset = m_offsets[jointId];
|
||||
--offset;
|
||||
m_points[offset] = {featureId, pointId};
|
||||
});
|
||||
});
|
||||
|
||||
CHECK_EQUAL(m_offsets[0], 0, ());
|
||||
CHECK_EQUAL(m_offsets.back(), m_points.size(), ());
|
||||
}
|
||||
} // namespace routing
|
69
routing/joint_index.hpp
Normal file
69
routing/joint_index.hpp
Normal file
|
@ -0,0 +1,69 @@
|
|||
#pragma once
|
||||
|
||||
#include "routing/joint.hpp"
|
||||
#include "routing/road_index.hpp"
|
||||
#include "routing/road_point.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
|
||||
#include "std/vector.hpp"
|
||||
|
||||
namespace routing
|
||||
{
|
||||
// JointIndex contains mapping from Joint::Id to RoadPoints.
|
||||
//
|
||||
// It is vector<Joint> conceptually.
|
||||
// Technically Joint entries are joined into the single vector to reduce allocations overheads.
|
||||
class JointIndex final
|
||||
{
|
||||
public:
|
||||
// Read comments in Build method about -1.
|
||||
uint32_t GetNumJoints() const
|
||||
{
|
||||
CHECK_GREATER(m_offsets.size(), 0, ());
|
||||
return m_offsets.size() - 1;
|
||||
}
|
||||
|
||||
uint32_t GetNumPoints() const { return m_points.size(); }
|
||||
RoadPoint GetPoint(Joint::Id jointId) const { return m_points[Begin(jointId)]; }
|
||||
|
||||
template <typename F>
|
||||
void ForEachPoint(Joint::Id jointId, F && f) const
|
||||
{
|
||||
for (uint32_t i = Begin(jointId); i < End(jointId); ++i)
|
||||
f(m_points[i]);
|
||||
|
||||
auto const & it = m_dynamicJoints.find(jointId);
|
||||
if (it != m_dynamicJoints.end())
|
||||
{
|
||||
Joint const & joint = it->second;
|
||||
for (size_t i = 0; i < joint.GetSize(); ++i)
|
||||
f(joint.GetEntry(i));
|
||||
}
|
||||
}
|
||||
|
||||
void Build(RoadIndex const & roadIndex, uint32_t numJoints);
|
||||
Joint::Id InsertJoint(RoadPoint const & rp);
|
||||
void AppendToJoint(Joint::Id jointId, RoadPoint const & rp);
|
||||
|
||||
private:
|
||||
// Begin index for jointId entries.
|
||||
uint32_t Begin(Joint::Id jointId) const
|
||||
{
|
||||
ASSERT_LESS(jointId, m_offsets.size(), ());
|
||||
return m_offsets[jointId];
|
||||
}
|
||||
|
||||
// End index (not inclusive) for jointId entries.
|
||||
uint32_t End(Joint::Id jointId) const
|
||||
{
|
||||
Joint::Id const nextId = jointId + 1;
|
||||
ASSERT_LESS(nextId, m_offsets.size(), ());
|
||||
return m_offsets[nextId];
|
||||
}
|
||||
|
||||
vector<uint32_t> m_offsets;
|
||||
vector<RoadPoint> m_points;
|
||||
unordered_map<Joint::Id, Joint> m_dynamicJoints;
|
||||
};
|
||||
} // namespace routing
|
|
@ -6,12 +6,12 @@ namespace routing
|
|||
RestrictionLoader::RestrictionLoader(MwmValue const & mwmValue)
|
||||
: m_countryFileName(mwmValue.GetCountryFileName())
|
||||
{
|
||||
if (!mwmValue.m_cont.IsExist(ROUTING_FILE_TAG))
|
||||
if (!mwmValue.m_cont.IsExist(RESTRICTIONS_FILE_TAG))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
m_reader = make_unique<FilesContainerR::TReader>(mwmValue.m_cont.GetReader(ROUTING_FILE_TAG));
|
||||
m_reader = make_unique<FilesContainerR::TReader>(mwmValue.m_cont.GetReader(RESTRICTIONS_FILE_TAG));
|
||||
ReaderSource<FilesContainerR::TReader> src(*m_reader);
|
||||
m_header.Deserialize(src);
|
||||
|
||||
|
@ -21,7 +21,7 @@ RestrictionLoader::RestrictionLoader(MwmValue const & mwmValue)
|
|||
{
|
||||
m_header.Reset();
|
||||
LOG(LERROR,
|
||||
("File", m_countryFileName, "Error while reading", ROUTING_FILE_TAG, "section.", e.Msg()));
|
||||
("File", m_countryFileName, "Error while reading", RESTRICTIONS_FILE_TAG, "section.", e.Msg()));
|
||||
}
|
||||
}
|
||||
} // namespace routing
|
||||
|
|
|
@ -54,6 +54,7 @@ class Edge
|
|||
public:
|
||||
static Edge MakeFake(Junction const & startJunction, Junction const & endJunction);
|
||||
|
||||
Edge() : m_forward(true), m_segId(0) {}
|
||||
Edge(FeatureID const & featureId, bool forward, uint32_t segId, Junction const & startJunction, Junction const & endJunction);
|
||||
Edge(Edge const &) = default;
|
||||
Edge & operator=(Edge const &) = default;
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "routing/pedestrian_directions.hpp"
|
||||
#include "routing/pedestrian_model.hpp"
|
||||
#include "routing/route.hpp"
|
||||
#include "routing/routing_helpers.hpp"
|
||||
#include "routing/single_mwm_router.hpp"
|
||||
|
||||
#include "coding/reader_wrapper.hpp"
|
||||
|
||||
|
@ -225,7 +227,7 @@ IRouter::ResultCode RoadGraphRouter::CalculateRoute(m2::PointD const & startPoin
|
|||
ASSERT_EQUAL(result.path.front(), startPos, ());
|
||||
ASSERT_EQUAL(result.path.back(), finalPos, ());
|
||||
ASSERT_GREATER(result.distance, 0., ());
|
||||
ReconstructRoute(move(result.path), route, delegate);
|
||||
ReconstructRoute(m_directionsEngine.get(), *m_roadGraph, delegate, result.path, route);
|
||||
}
|
||||
|
||||
m_roadGraph->ResetFakes();
|
||||
|
@ -246,39 +248,6 @@ IRouter::ResultCode RoadGraphRouter::CalculateRoute(m2::PointD const & startPoin
|
|||
return IRouter::RouteNotFound;
|
||||
}
|
||||
|
||||
void RoadGraphRouter::ReconstructRoute(vector<Junction> && path, Route & route,
|
||||
my::Cancellable const & cancellable) const
|
||||
{
|
||||
CHECK(!path.empty(), ("Can't reconstruct route from an empty list of positions."));
|
||||
|
||||
// By some reason there're two adjacent positions on a road with
|
||||
// the same end-points. This could happen, for example, when
|
||||
// direction on a road was changed. But it doesn't matter since
|
||||
// this code reconstructs only geometry of a route.
|
||||
path.erase(unique(path.begin(), path.end()), path.end());
|
||||
if (path.size() == 1)
|
||||
path.emplace_back(path.back());
|
||||
|
||||
Route::TTimes times;
|
||||
Route::TTurns turnsDir;
|
||||
vector<Junction> junctions;
|
||||
// @TODO(bykoianko) streetNames is not filled in Generate(). It should be done.
|
||||
Route::TStreets streetNames;
|
||||
if (m_directionsEngine)
|
||||
m_directionsEngine->Generate(*m_roadGraph, path, times, turnsDir, junctions, cancellable);
|
||||
|
||||
vector<m2::PointD> routeGeometry;
|
||||
JunctionsToPoints(junctions, routeGeometry);
|
||||
feature::TAltitudes altitudes;
|
||||
JunctionsToAltitudes(junctions, altitudes);
|
||||
|
||||
route.SetGeometry(routeGeometry.begin(), routeGeometry.end());
|
||||
route.SetSectionTimes(move(times));
|
||||
route.SetTurnInstructions(move(turnsDir));
|
||||
route.SetStreetNames(move(streetNames));
|
||||
route.SetAltitudes(move(altitudes));
|
||||
}
|
||||
|
||||
unique_ptr<IRouter> CreatePedestrianAStarRouter(Index & index, TCountryFileFn const & countryFileFn)
|
||||
{
|
||||
unique_ptr<VehicleModelFactory> vehicleModelFactory(new PedestrianModelFactory());
|
||||
|
@ -311,18 +280,4 @@ unique_ptr<IRouter> CreateBicycleAStarBidirectionalRouter(Index & index, TCountr
|
|||
move(vehicleModelFactory), move(algorithm), move(directionsEngine)));
|
||||
return router;
|
||||
}
|
||||
|
||||
unique_ptr<IRouter> CreateCarAStarBidirectionalRouter(Index & index,
|
||||
TCountryFileFn const & countryFileFn)
|
||||
{
|
||||
unique_ptr<VehicleModelFactory> vehicleModelFactory = make_unique<CarModelFactory>();
|
||||
unique_ptr<IRoutingAlgorithm> algorithm = make_unique<AStarBidirectionalRoutingAlgorithm>();
|
||||
// @TODO Bicycle turn generation engine is used now. It's ok for the time being.
|
||||
// But later a special car turn generation engine should be implemented.
|
||||
unique_ptr<IDirectionsEngine> directionsEngine = make_unique<BicycleDirectionsEngine>(index);
|
||||
unique_ptr<IRouter> router = make_unique<RoadGraphRouter>(
|
||||
"astar-bidirectional-car", index, countryFileFn, IRoadGraph::Mode::ObeyOnewayTag,
|
||||
move(vehicleModelFactory), move(algorithm), move(directionsEngine));
|
||||
return router;
|
||||
}
|
||||
} // namespace routing
|
||||
|
|
|
@ -37,9 +37,6 @@ public:
|
|||
Route & route) override;
|
||||
|
||||
private:
|
||||
void ReconstructRoute(vector<Junction> && junctions, Route & route,
|
||||
my::Cancellable const & cancellable) const;
|
||||
|
||||
/// Checks existance and add absent maps to route.
|
||||
/// Returns true if map exists
|
||||
bool CheckMapExistence(m2::PointD const & point, Route & route) const;
|
||||
|
@ -55,6 +52,4 @@ private:
|
|||
unique_ptr<IRouter> CreatePedestrianAStarRouter(Index & index, TCountryFileFn const & countryFileFn);
|
||||
unique_ptr<IRouter> CreatePedestrianAStarBidirectionalRouter(Index & index, TCountryFileFn const & countryFileFn);
|
||||
unique_ptr<IRouter> CreateBicycleAStarBidirectionalRouter(Index & index, TCountryFileFn const & countryFileFn);
|
||||
unique_ptr<IRouter> CreateCarAStarBidirectionalRouter(Index & index,
|
||||
TCountryFileFn const & countryFileFn);
|
||||
} // namespace routing
|
||||
|
|
29
routing/road_index.cpp
Normal file
29
routing/road_index.cpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
#include "routing/road_index.hpp"
|
||||
|
||||
#include "routing/routing_exception.hpp"
|
||||
|
||||
namespace routing
|
||||
{
|
||||
void RoadIndex::Import(vector<Joint> const & joints)
|
||||
{
|
||||
for (Joint::Id jointId = 0; jointId < joints.size(); ++jointId)
|
||||
{
|
||||
Joint const & joint = joints[jointId];
|
||||
for (uint32_t i = 0; i < joint.GetSize(); ++i)
|
||||
{
|
||||
RoadPoint const & entry = joint.GetEntry(i);
|
||||
RoadJointIds & roadJoints = m_roads[entry.GetFeatureId()];
|
||||
roadJoints.AddJoint(entry.GetPointId(), jointId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pair<Joint::Id, uint32_t> RoadIndex::FindNeighbor(RoadPoint const & rp, bool forward) const
|
||||
{
|
||||
auto const it = m_roads.find(rp.GetFeatureId());
|
||||
if (it == m_roads.cend())
|
||||
MYTHROW(RoutingException, ("RoadIndex doesn't contains feature", rp.GetFeatureId()));
|
||||
|
||||
return it->second.FindNeighbor(rp.GetPointId(), forward);
|
||||
}
|
||||
} // namespace routing
|
168
routing/road_index.hpp
Normal file
168
routing/road_index.hpp
Normal file
|
@ -0,0 +1,168 @@
|
|||
#pragma once
|
||||
|
||||
#include "routing/joint.hpp"
|
||||
|
||||
#include "coding/reader.hpp"
|
||||
#include "coding/write_to_sink.hpp"
|
||||
|
||||
#include "std/algorithm.hpp"
|
||||
#include "std/cstdint.hpp"
|
||||
#include "std/unordered_map.hpp"
|
||||
#include "std/utility.hpp"
|
||||
#include "std/vector.hpp"
|
||||
|
||||
namespace routing
|
||||
{
|
||||
class RoadJointIds final
|
||||
{
|
||||
public:
|
||||
Joint::Id GetJointId(uint32_t pointId) const
|
||||
{
|
||||
if (pointId < m_jointIds.size())
|
||||
return m_jointIds[pointId];
|
||||
|
||||
return Joint::kInvalidId;
|
||||
}
|
||||
|
||||
void AddJoint(uint32_t pointId, Joint::Id jointId)
|
||||
{
|
||||
if (pointId >= m_jointIds.size())
|
||||
m_jointIds.insert(m_jointIds.end(), pointId + 1 - m_jointIds.size(), Joint::kInvalidId);
|
||||
|
||||
ASSERT_EQUAL(m_jointIds[pointId], Joint::kInvalidId, ());
|
||||
m_jointIds[pointId] = jointId;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void ForEachJoint(F && f) const
|
||||
{
|
||||
for (uint32_t pointId = 0; pointId < m_jointIds.size(); ++pointId)
|
||||
{
|
||||
Joint::Id const jointId = m_jointIds[pointId];
|
||||
if (jointId != Joint::kInvalidId)
|
||||
f(pointId, jointId);
|
||||
}
|
||||
}
|
||||
|
||||
pair<Joint::Id, uint32_t> FindNeighbor(uint32_t pointId, bool forward) const
|
||||
{
|
||||
uint32_t const size = static_cast<uint32_t>(m_jointIds.size());
|
||||
pair<Joint::Id, uint32_t> result = make_pair(Joint::kInvalidId, 0);
|
||||
|
||||
if (forward)
|
||||
{
|
||||
for (uint32_t i = pointId + 1; i < size; ++i)
|
||||
{
|
||||
Joint::Id const jointId = m_jointIds[i];
|
||||
if (jointId != Joint::kInvalidId)
|
||||
{
|
||||
result = {jointId, i};
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t i = min(pointId, size) - 1; i < size; --i)
|
||||
{
|
||||
Joint::Id const jointId = m_jointIds[i];
|
||||
if (jointId != Joint::kInvalidId)
|
||||
{
|
||||
result = {jointId, i};
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class Sink>
|
||||
void Serialize(Sink & sink) const
|
||||
{
|
||||
WriteToSink(sink, static_cast<Joint::Id>(m_jointIds.size()));
|
||||
for (Joint::Id jointId : m_jointIds)
|
||||
WriteToSink(sink, jointId);
|
||||
}
|
||||
|
||||
template <class Source>
|
||||
void Deserialize(Source & src)
|
||||
{
|
||||
m_jointIds.clear();
|
||||
Joint::Id const jointsSize = ReadPrimitiveFromSource<Joint::Id>(src);
|
||||
m_jointIds.reserve(jointsSize);
|
||||
for (Joint::Id i = 0; i < jointsSize; ++i)
|
||||
{
|
||||
Joint::Id const jointId = ReadPrimitiveFromSource<Joint::Id>(src);
|
||||
m_jointIds.emplace_back(jointId);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// Joint ids indexed by point id.
|
||||
// If some point id doesn't match any joint id, this vector contains Joint::kInvalidId.
|
||||
vector<Joint::Id> m_jointIds;
|
||||
};
|
||||
|
||||
class RoadIndex final
|
||||
{
|
||||
public:
|
||||
void Import(vector<Joint> const & joints);
|
||||
|
||||
void AddJoint(RoadPoint const & rp, Joint::Id jointId)
|
||||
{
|
||||
m_roads[rp.GetFeatureId()].AddJoint(rp.GetPointId(), jointId);
|
||||
}
|
||||
|
||||
// Find nearest point with normal joint id.
|
||||
// If forward == true: neighbor with larger point id (right neighbor)
|
||||
// If forward == false: neighbor with smaller point id (left neighbor)
|
||||
pair<Joint::Id, uint32_t> FindNeighbor(RoadPoint const & rp, bool forward) const;
|
||||
|
||||
template <class Sink>
|
||||
void Serialize(Sink & sink) const
|
||||
{
|
||||
WriteToSink(sink, static_cast<uint32_t>(m_roads.size()));
|
||||
for (auto const & it : m_roads)
|
||||
{
|
||||
uint32_t const featureId = it.first;
|
||||
WriteToSink(sink, featureId);
|
||||
it.second.Serialize(sink);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Source>
|
||||
void Deserialize(Source & src)
|
||||
{
|
||||
m_roads.clear();
|
||||
size_t const roadsSize = static_cast<size_t>(ReadPrimitiveFromSource<uint32_t>(src));
|
||||
for (size_t i = 0; i < roadsSize; ++i)
|
||||
{
|
||||
uint32_t featureId = ReadPrimitiveFromSource<decltype(featureId)>(src);
|
||||
m_roads[featureId].Deserialize(src);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t GetSize() const { return m_roads.size(); }
|
||||
|
||||
Joint::Id GetJointId(RoadPoint const & rp) const
|
||||
{
|
||||
auto const it = m_roads.find(rp.GetFeatureId());
|
||||
if (it == m_roads.end())
|
||||
return Joint::kInvalidId;
|
||||
|
||||
return it->second.GetJointId(rp.GetPointId());
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void ForEachRoad(F && f) const
|
||||
{
|
||||
for (auto const & it : m_roads)
|
||||
f(it.first, it.second);
|
||||
}
|
||||
|
||||
private:
|
||||
// Map from feature id to RoadJointIds.
|
||||
unordered_map<uint32_t, RoadJointIds> m_roads;
|
||||
};
|
||||
} // namespace routing
|
41
routing/road_point.hpp
Normal file
41
routing/road_point.hpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
|
||||
#include "std/cstdint.hpp"
|
||||
#include "std/sstream.hpp"
|
||||
#include "std/string.hpp"
|
||||
|
||||
namespace routing
|
||||
{
|
||||
// RoadPoint in unique identifier for any road point in mwm file.
|
||||
//
|
||||
// Contains feature id and point id.
|
||||
// Point id is the ordinal number of point in the road.
|
||||
class RoadPoint final
|
||||
{
|
||||
public:
|
||||
RoadPoint() : m_featureId(0), m_pointId(0) {}
|
||||
|
||||
RoadPoint(uint32_t featureId, uint32_t pointId) : m_featureId(featureId), m_pointId(pointId) {}
|
||||
|
||||
uint32_t GetFeatureId() const { return m_featureId; }
|
||||
|
||||
uint32_t GetPointId() const { return m_pointId; }
|
||||
|
||||
bool operator==(RoadPoint const & rp) const
|
||||
{
|
||||
return m_featureId == rp.m_featureId && m_pointId == rp.m_pointId;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t m_featureId;
|
||||
uint32_t m_pointId;
|
||||
};
|
||||
|
||||
inline string DebugPrint(RoadPoint const & rp)
|
||||
{
|
||||
ostringstream out;
|
||||
out << "rp("
|
||||
<< "(" << rp.GetFeatureId() << ", " << rp.GetPointId() << ")";
|
||||
return out.str();
|
||||
}
|
||||
} // namespace routing
|
|
@ -23,7 +23,13 @@ SOURCES += \
|
|||
cross_mwm_router.cpp \
|
||||
cross_routing_context.cpp \
|
||||
directions_engine.cpp \
|
||||
edge_estimator.cpp \
|
||||
features_road_graph.cpp \
|
||||
geometry.cpp \
|
||||
index_graph.cpp \
|
||||
index_graph_starter.cpp \
|
||||
joint.cpp \
|
||||
joint_index.cpp \
|
||||
nearest_edge_finder.cpp \
|
||||
online_absent_fetcher.cpp \
|
||||
online_cross_fetcher.cpp \
|
||||
|
@ -36,13 +42,16 @@ SOURCES += \
|
|||
restriction_loader.cpp \
|
||||
road_graph.cpp \
|
||||
road_graph_router.cpp \
|
||||
road_index.cpp \
|
||||
route.cpp \
|
||||
router.cpp \
|
||||
router_delegate.cpp \
|
||||
routing_algorithm.cpp \
|
||||
routing_helpers.cpp \
|
||||
routing_mapping.cpp \
|
||||
routing_serialization.cpp \
|
||||
routing_session.cpp \
|
||||
single_mwm_router.cpp \
|
||||
speed_camera.cpp \
|
||||
turns.cpp \
|
||||
turns_generator.cpp \
|
||||
|
@ -64,7 +73,13 @@ HEADERS += \
|
|||
cross_mwm_router.hpp \
|
||||
cross_routing_context.hpp \
|
||||
directions_engine.hpp \
|
||||
edge_estimator.hpp \
|
||||
features_road_graph.hpp \
|
||||
geometry.hpp \
|
||||
index_graph.hpp \
|
||||
index_graph_starter.hpp \
|
||||
joint.hpp \
|
||||
joint_index.hpp \
|
||||
loaded_path_segment.hpp \
|
||||
nearest_edge_finder.hpp \
|
||||
online_absent_fetcher.hpp \
|
||||
|
@ -79,16 +94,20 @@ HEADERS += \
|
|||
restriction_loader.hpp \
|
||||
road_graph.hpp \
|
||||
road_graph_router.hpp \
|
||||
road_index.hpp \
|
||||
road_point.hpp \
|
||||
route.hpp \
|
||||
router.hpp \
|
||||
router_delegate.hpp \
|
||||
routing_algorithm.hpp \
|
||||
routing_exception.hpp \
|
||||
routing_helpers.hpp \
|
||||
routing_mapping.hpp \
|
||||
routing_result_graph.hpp \
|
||||
routing_serialization.hpp \
|
||||
routing_session.hpp \
|
||||
routing_settings.hpp \
|
||||
single_mwm_router.hpp \
|
||||
speed_camera.hpp \
|
||||
turn_candidate.hpp \
|
||||
turns.hpp \
|
||||
|
|
|
@ -151,8 +151,9 @@ IRoutingAlgorithm::Result AStarRoutingAlgorithm::CalculateRoute(IRoadGraph const
|
|||
|
||||
my::Cancellable const & cancellable = delegate;
|
||||
progress.Initialize(startPos.GetPoint(), finalPos.GetPoint());
|
||||
RoadGraph roadGraph(graph);
|
||||
TAlgorithmImpl::Result const res = TAlgorithmImpl().FindPath(
|
||||
RoadGraph(graph), startPos, finalPos, path, cancellable, onVisitJunctionFn);
|
||||
roadGraph, startPos, finalPos, path, cancellable, onVisitJunctionFn);
|
||||
return Convert(res);
|
||||
}
|
||||
|
||||
|
@ -177,8 +178,9 @@ IRoutingAlgorithm::Result AStarBidirectionalRoutingAlgorithm::CalculateRoute(
|
|||
|
||||
my::Cancellable const & cancellable = delegate;
|
||||
progress.Initialize(startPos.GetPoint(), finalPos.GetPoint());
|
||||
RoadGraph roadGraph(graph);
|
||||
TAlgorithmImpl::Result const res = TAlgorithmImpl().FindPathBidirectional(
|
||||
RoadGraph(graph), startPos, finalPos, path, cancellable, onVisitJunctionFn);
|
||||
roadGraph, startPos, finalPos, path, cancellable, onVisitJunctionFn);
|
||||
return Convert(res);
|
||||
}
|
||||
|
||||
|
|
8
routing/routing_exception.hpp
Normal file
8
routing/routing_exception.hpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "base/exception.hpp"
|
||||
|
||||
namespace routing
|
||||
{
|
||||
DECLARE_EXCEPTION(RoutingException, RootException);
|
||||
} // namespace routing
|
39
routing/routing_helpers.cpp
Normal file
39
routing/routing_helpers.cpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
#include "routing/routing_helpers.hpp"
|
||||
|
||||
namespace routing
|
||||
{
|
||||
void ReconstructRoute(IDirectionsEngine * engine, IRoadGraph const & graph,
|
||||
my::Cancellable const & cancellable, vector<Junction> & path, Route & route)
|
||||
{
|
||||
if (path.empty())
|
||||
{
|
||||
LOG(LERROR, ("Can't reconstruct route from an empty list of positions."));
|
||||
return;
|
||||
}
|
||||
|
||||
// By some reason there're two adjacent positions on a road with
|
||||
// the same end-points. This could happen, for example, when
|
||||
// direction on a road was changed. But it doesn't matter since
|
||||
// this code reconstructs only geometry of a route.
|
||||
path.erase(unique(path.begin(), path.end()), path.end());
|
||||
|
||||
Route::TTimes times;
|
||||
Route::TTurns turnsDir;
|
||||
vector<Junction> junctions;
|
||||
// @TODO(bykoianko) streetNames is not filled in Generate(). It should be done.
|
||||
Route::TStreets streetNames;
|
||||
if (engine)
|
||||
engine->Generate(graph, path, times, turnsDir, junctions, cancellable);
|
||||
|
||||
vector<m2::PointD> routeGeometry;
|
||||
JunctionsToPoints(junctions, routeGeometry);
|
||||
feature::TAltitudes altitudes;
|
||||
JunctionsToAltitudes(junctions, altitudes);
|
||||
|
||||
route.SetGeometry(routeGeometry.begin(), routeGeometry.end());
|
||||
route.SetSectionTimes(move(times));
|
||||
route.SetTurnInstructions(move(turnsDir));
|
||||
route.SetStreetNames(move(streetNames));
|
||||
route.SetAltitudes(move(altitudes));
|
||||
}
|
||||
} // namespace rouing
|
|
@ -2,7 +2,14 @@
|
|||
|
||||
#include "routing/bicycle_model.hpp"
|
||||
#include "routing/car_model.hpp"
|
||||
#include "routing/directions_engine.hpp"
|
||||
#include "routing/pedestrian_model.hpp"
|
||||
#include "routing/road_graph.hpp"
|
||||
#include "routing/route.hpp"
|
||||
|
||||
#include "base/cancellable.hpp"
|
||||
|
||||
#include "std/vector.hpp"
|
||||
|
||||
namespace routing
|
||||
{
|
||||
|
@ -14,4 +21,7 @@ bool IsRoad(TTypes const & types)
|
|||
PedestrianModel::AllLimitsInstance().HasRoadType(types) ||
|
||||
BicycleModel::AllLimitsInstance().HasRoadType(types);
|
||||
}
|
||||
|
||||
void ReconstructRoute(IDirectionsEngine * engine, IRoadGraph const & graph,
|
||||
my::Cancellable const & cancellable, vector<Junction> & path, Route & route);
|
||||
} // namespace rouing
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "routing/road_graph_router.hpp"
|
||||
#include "routing/route.hpp"
|
||||
#include "routing/router_delegate.hpp"
|
||||
#include "routing/single_mwm_router.hpp"
|
||||
|
||||
#include "indexer/index.hpp"
|
||||
|
||||
|
@ -82,7 +83,7 @@ namespace integration
|
|||
};
|
||||
|
||||
auto carRouter = make_unique<CarRouter>(
|
||||
index, countryFileGetter, CreateCarAStarBidirectionalRouter(index, countryFileGetter));
|
||||
index, countryFileGetter, SingleMwmRouter::CreateCarRouter(index));
|
||||
return carRouter;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ private:
|
|||
map<unsigned, vector<Edge>> m_adjs;
|
||||
};
|
||||
|
||||
void TestAStar(UndirectedGraph const & graph, vector<unsigned> const & expectedRoute, double const & expectedDistance)
|
||||
void TestAStar(UndirectedGraph & graph, vector<unsigned> const & expectedRoute, double const & expectedDistance)
|
||||
{
|
||||
using TAlgorithm = AStarAlgorithm<UndirectedGraph>;
|
||||
|
||||
|
|
338
routing/routing_tests/index_graph_test.cpp
Normal file
338
routing/routing_tests/index_graph_test.cpp
Normal file
|
@ -0,0 +1,338 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "routing/base/astar_algorithm.hpp"
|
||||
#include "routing/car_model.hpp"
|
||||
#include "routing/edge_estimator.hpp"
|
||||
#include "routing/index_graph.hpp"
|
||||
#include "routing/index_graph_starter.hpp"
|
||||
|
||||
#include "geometry/point2d.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
|
||||
#include "std/algorithm.hpp"
|
||||
#include "std/unique_ptr.hpp"
|
||||
#include "std/unordered_map.hpp"
|
||||
#include "std/vector.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
using namespace routing;
|
||||
|
||||
class TestGeometryLoader final : public GeometryLoader
|
||||
{
|
||||
public:
|
||||
// GeometryLoader overrides:
|
||||
void Load(uint32_t featureId, RoadGeometry & road) const override;
|
||||
|
||||
void AddRoad(uint32_t featureId, bool oneWay, float speed, RoadGeometry::Points const & points);
|
||||
|
||||
private:
|
||||
unordered_map<uint32_t, RoadGeometry> m_roads;
|
||||
};
|
||||
|
||||
void TestGeometryLoader::Load(uint32_t featureId, RoadGeometry & road) const
|
||||
{
|
||||
auto it = m_roads.find(featureId);
|
||||
if (it == m_roads.cend())
|
||||
return;
|
||||
|
||||
road = it->second;
|
||||
}
|
||||
|
||||
void TestGeometryLoader::AddRoad(uint32_t featureId, bool oneWay, float speed,
|
||||
RoadGeometry::Points const & points)
|
||||
{
|
||||
auto it = m_roads.find(featureId);
|
||||
CHECK(it == m_roads.end(), ("Already contains feature", featureId));
|
||||
m_roads[featureId] = RoadGeometry(oneWay, speed, points);
|
||||
}
|
||||
|
||||
Joint MakeJoint(vector<RoadPoint> const & points)
|
||||
{
|
||||
Joint joint;
|
||||
for (auto const & point : points)
|
||||
joint.AddPoint(point);
|
||||
|
||||
return joint;
|
||||
}
|
||||
|
||||
shared_ptr<EdgeEstimator> CreateEstimator()
|
||||
{
|
||||
return EdgeEstimator::CreateForCar(*make_shared<CarModelFactory>()->GetVehicleModel());
|
||||
}
|
||||
|
||||
void TestRoute(IndexGraph & graph, RoadPoint const & start, RoadPoint const & finish,
|
||||
size_t expectedLength, vector<RoadPoint> const * expectedRoute = nullptr)
|
||||
{
|
||||
LOG(LINFO, ("Test route", start.GetFeatureId(), ",", start.GetPointId(), "=>",
|
||||
finish.GetFeatureId(), ",", finish.GetPointId()));
|
||||
|
||||
AStarAlgorithm<IndexGraphStarter> algorithm;
|
||||
RoutingResult<Joint::Id> routingResult;
|
||||
|
||||
IndexGraphStarter starter(graph, start, finish);
|
||||
auto const resultCode = algorithm.FindPath(starter, starter.GetStartJoint(),
|
||||
starter.GetFinishJoint(), routingResult, {}, {});
|
||||
TEST_EQUAL(resultCode, AStarAlgorithm<IndexGraphStarter>::Result::OK, ());
|
||||
|
||||
vector<RoadPoint> roadPoints;
|
||||
starter.RedressRoute(routingResult.path, roadPoints);
|
||||
TEST_EQUAL(roadPoints.size(), expectedLength, ());
|
||||
|
||||
if (expectedRoute)
|
||||
TEST_EQUAL(roadPoints, *expectedRoute, ());
|
||||
}
|
||||
|
||||
void TestEdges(IndexGraph & graph, Joint::Id jointId, vector<Joint::Id> const & expectedTargets,
|
||||
bool forward)
|
||||
{
|
||||
vector<JointEdge> edges;
|
||||
graph.GetEdgeList(jointId, forward, edges);
|
||||
|
||||
vector<Joint::Id> targets;
|
||||
for (JointEdge const & edge : edges)
|
||||
targets.push_back(edge.GetTarget());
|
||||
|
||||
sort(targets.begin(), targets.end());
|
||||
|
||||
TEST_EQUAL(targets, expectedTargets, ());
|
||||
}
|
||||
|
||||
void TestOutgoingEdges(IndexGraph & graph, Joint::Id jointId,
|
||||
vector<Joint::Id> const & expectedTargets)
|
||||
{
|
||||
TestEdges(graph, jointId, expectedTargets, true);
|
||||
}
|
||||
|
||||
void TestIngoingEdges(IndexGraph & graph, Joint::Id jointId,
|
||||
vector<Joint::Id> const & expectedTargets)
|
||||
{
|
||||
TestEdges(graph, jointId, expectedTargets, false);
|
||||
}
|
||||
|
||||
uint32_t AbsDelta(uint32_t v0, uint32_t v1) { return v0 > v1 ? v0 - v1 : v1 - v0; }
|
||||
} // namespace
|
||||
|
||||
namespace routing_test
|
||||
{
|
||||
// R4 (one way down)
|
||||
//
|
||||
// R1 J2--------J3 -1
|
||||
// ^ v
|
||||
// ^ v
|
||||
// R0 *---J0----*---J1----* 0
|
||||
// ^ v
|
||||
// ^ v
|
||||
// R2 J4--------J5 1
|
||||
//
|
||||
// R3 (one way up) y
|
||||
//
|
||||
// x: 0 1 2 3 4
|
||||
//
|
||||
UNIT_TEST(EdgesTest)
|
||||
{
|
||||
unique_ptr<TestGeometryLoader> loader = make_unique<TestGeometryLoader>();
|
||||
loader->AddRoad(
|
||||
0 /* featureId */, false, 1.0 /* speed */,
|
||||
RoadGeometry::Points({{0.0, 0.0}, {1.0, 0.0}, {2.0, 0.0}, {3.0, 0.0}, {4.0, 0.0}}));
|
||||
loader->AddRoad(1 /* featureId */, false, 1.0 /* speed */,
|
||||
RoadGeometry::Points({{1.0, -1.0}, {3.0, -1.0}}));
|
||||
loader->AddRoad(2 /* featureId */, false, 1.0 /* speed */,
|
||||
RoadGeometry::Points({{1.0, -1.0}, {3.0, -1.0}}));
|
||||
loader->AddRoad(3 /* featureId */, true, 1.0 /* speed */,
|
||||
RoadGeometry::Points({{1.0, 1.0}, {1.0, 0.0}, {1.0, -1.0}}));
|
||||
loader->AddRoad(4 /* featureId */, true, 1.0 /* speed */,
|
||||
RoadGeometry::Points({{3.0, -1.0}, {3.0, 0.0}, {3.0, 1.0}}));
|
||||
|
||||
IndexGraph graph(move(loader), CreateEstimator());
|
||||
|
||||
vector<Joint> joints;
|
||||
joints.emplace_back(MakeJoint({{0, 1}, {3, 1}})); // J0
|
||||
joints.emplace_back(MakeJoint({{0, 3}, {4, 1}})); // J1
|
||||
joints.emplace_back(MakeJoint({{1, 0}, {3, 2}})); // J2
|
||||
joints.emplace_back(MakeJoint({{1, 1}, {4, 0}})); // J3
|
||||
joints.emplace_back(MakeJoint({{2, 0}, {3, 0}})); // J4
|
||||
joints.emplace_back(MakeJoint({{2, 1}, {4, 2}})); // J5
|
||||
graph.Import(joints);
|
||||
|
||||
TestOutgoingEdges(graph, 0, {1, 2});
|
||||
TestOutgoingEdges(graph, 1, {0, 5});
|
||||
TestOutgoingEdges(graph, 2, {3});
|
||||
TestOutgoingEdges(graph, 3, {1, 2});
|
||||
TestOutgoingEdges(graph, 4, {0, 5});
|
||||
TestOutgoingEdges(graph, 5, {4});
|
||||
|
||||
TestIngoingEdges(graph, 0, {1, 4});
|
||||
TestIngoingEdges(graph, 1, {0, 3});
|
||||
TestIngoingEdges(graph, 2, {0, 3});
|
||||
TestIngoingEdges(graph, 3, {2});
|
||||
TestIngoingEdges(graph, 4, {5});
|
||||
TestIngoingEdges(graph, 5, {1, 4});
|
||||
}
|
||||
|
||||
// Roads R1:
|
||||
//
|
||||
// -2
|
||||
// -1
|
||||
// R0 -2 -1 0 1 2
|
||||
// 1
|
||||
// 2
|
||||
//
|
||||
UNIT_TEST(FindPathCross)
|
||||
{
|
||||
unique_ptr<TestGeometryLoader> loader = make_unique<TestGeometryLoader>();
|
||||
loader->AddRoad(
|
||||
0 /* featureId */, false, 1.0 /* speed */,
|
||||
RoadGeometry::Points({{-2.0, 0.0}, {-1.0, 0.0}, {0.0, 0.0}, {1.0, 0.0}, {2.0, 0.0}}));
|
||||
loader->AddRoad(
|
||||
1 /* featureId */, false, 1.0 /* speed */,
|
||||
RoadGeometry::Points({{0.0, -2.0}, {-1.0, 0.0}, {0.0, 0.0}, {0.0, 1.0}, {0.0, 2.0}}));
|
||||
|
||||
IndexGraph graph(move(loader), CreateEstimator());
|
||||
|
||||
graph.Import({MakeJoint({{0, 2}, {1, 2}})});
|
||||
|
||||
vector<RoadPoint> points;
|
||||
for (uint32_t i = 0; i < 5; ++i)
|
||||
{
|
||||
points.emplace_back(0, i);
|
||||
points.emplace_back(1, i);
|
||||
}
|
||||
|
||||
for (auto const & start : points)
|
||||
{
|
||||
for (auto const & finish : points)
|
||||
{
|
||||
uint32_t expectedLength;
|
||||
// Length of the route is the number of route points.
|
||||
// Example: p0 --- p1 --- p2
|
||||
// 2 segments, 3 points,
|
||||
// Therefore route length = geometrical length + 1
|
||||
if (start.GetFeatureId() == finish.GetFeatureId())
|
||||
expectedLength = AbsDelta(start.GetPointId(), finish.GetPointId()) + 1;
|
||||
else
|
||||
expectedLength = AbsDelta(start.GetPointId(), 2) + AbsDelta(finish.GetPointId(), 2) + 1;
|
||||
TestRoute(graph, start, finish, expectedLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Roads R4 R5 R6 R7
|
||||
//
|
||||
// R0 0 - * - * - *
|
||||
// | | | |
|
||||
// R1 * - 1 - * - *
|
||||
// | | | |
|
||||
// R2 * - * - 2 - *
|
||||
// | | | |
|
||||
// R3 * - * - * - 3
|
||||
//
|
||||
UNIT_TEST(FindPathManhattan)
|
||||
{
|
||||
uint32_t constexpr kCitySize = 4;
|
||||
unique_ptr<TestGeometryLoader> loader = make_unique<TestGeometryLoader>();
|
||||
for (uint32_t i = 0; i < kCitySize; ++i)
|
||||
{
|
||||
RoadGeometry::Points street;
|
||||
RoadGeometry::Points avenue;
|
||||
for (uint32_t j = 0; j < kCitySize; ++j)
|
||||
{
|
||||
street.emplace_back(static_cast<double>(i), static_cast<double>(j));
|
||||
avenue.emplace_back(static_cast<double>(j), static_cast<double>(i));
|
||||
}
|
||||
loader->AddRoad(i, false, 1.0 /* speed */, street);
|
||||
loader->AddRoad(i + kCitySize, false, 1.0 /* speed */, avenue);
|
||||
}
|
||||
|
||||
IndexGraph graph(move(loader), CreateEstimator());
|
||||
|
||||
vector<Joint> joints;
|
||||
for (uint32_t i = 0; i < kCitySize; ++i)
|
||||
{
|
||||
for (uint32_t j = 0; j < kCitySize; ++j)
|
||||
joints.emplace_back(MakeJoint({{i, j}, {j + kCitySize, i}}));
|
||||
}
|
||||
graph.Import(joints);
|
||||
|
||||
for (uint32_t startY = 0; startY < kCitySize; ++startY)
|
||||
{
|
||||
for (uint32_t startX = 0; startX < kCitySize; ++startX)
|
||||
{
|
||||
for (uint32_t finishY = 0; finishY < kCitySize; ++finishY)
|
||||
{
|
||||
for (uint32_t finishX = 0; finishX < kCitySize; ++finishX)
|
||||
TestRoute(graph, {startX, startY}, {finishX, finishY},
|
||||
AbsDelta(startX, finishX) + AbsDelta(startY, finishY) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Roads y:
|
||||
//
|
||||
// R0: * - * - * -1
|
||||
// / \
|
||||
// R1: J0 * -* - * - *- * J1 0
|
||||
// \ /
|
||||
// R2: * - * - * 1
|
||||
//
|
||||
// x: 0 1 2 3 4
|
||||
//
|
||||
UNIT_TEST(RedressRace)
|
||||
{
|
||||
unique_ptr<TestGeometryLoader> loader = make_unique<TestGeometryLoader>();
|
||||
|
||||
loader->AddRoad(
|
||||
0 /* featureId */, false, 1.0 /* speed */,
|
||||
RoadGeometry::Points({{0.0, 0.0}, {1.0, -1.0}, {2.0, -1.0}, {3.0, -1.0}, {4.0, 0.0}}));
|
||||
|
||||
loader->AddRoad(
|
||||
1 /* featureId */, false, 1.0 /* speed */,
|
||||
RoadGeometry::Points({{0.0, 0.0}, {1.0, 0.0}, {2.0, 0.0}, {3.0, 0.0}, {4.0, 0.0}}));
|
||||
|
||||
loader->AddRoad(
|
||||
2 /* featureId */, false, 1.0 /* speed */,
|
||||
RoadGeometry::Points({{0.0, 0.0}, {1.0, 1.0}, {2.0, 1.0}, {3.0, 1.0}, {4.0, 0.0}}));
|
||||
|
||||
IndexGraph graph(move(loader), CreateEstimator());
|
||||
|
||||
vector<Joint> joints;
|
||||
joints.emplace_back(MakeJoint({{0, 0}, {1, 0}, {2, 0}})); // J0
|
||||
joints.emplace_back(MakeJoint({{0, 4}, {1, 4}, {2, 4}})); // J1
|
||||
graph.Import(joints);
|
||||
|
||||
vector<RoadPoint> const expectedRoute({{1, 0}, {1, 1}, {1, 2}, {1, 3}, {1, 4}});
|
||||
TestRoute(graph, {0, 0}, {0, 4}, 5, &expectedRoute);
|
||||
}
|
||||
|
||||
// Roads y:
|
||||
//
|
||||
// fast road R0 * - * - * -1
|
||||
// / \
|
||||
// slow road R1 J0 * - - * - - * J1 0
|
||||
//
|
||||
// x: 0 1 2 3 4
|
||||
//
|
||||
UNIT_TEST(RoadSpeed)
|
||||
{
|
||||
unique_ptr<TestGeometryLoader> loader = make_unique<TestGeometryLoader>();
|
||||
|
||||
loader->AddRoad(
|
||||
0 /* featureId */, false, 10.0 /* speed */,
|
||||
RoadGeometry::Points({{0.0, 0.0}, {1.0, -1.0}, {2.0, -1.0}, {3.0, -1.0}, {4.0, 0.0}}));
|
||||
|
||||
loader->AddRoad(1 /* featureId */, false, 1.0 /* speed */,
|
||||
RoadGeometry::Points({{0.0, 0.0}, {2.0, 0.0}, {4.0, 0.0}}));
|
||||
|
||||
IndexGraph graph(move(loader), CreateEstimator());
|
||||
|
||||
vector<Joint> joints;
|
||||
joints.emplace_back(MakeJoint({{0, 0}, {1, 0}})); // J0
|
||||
joints.emplace_back(MakeJoint({{0, 4}, {1, 2}})); // J1
|
||||
graph.Import(joints);
|
||||
|
||||
vector<RoadPoint> const expectedRoute({{0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 4}});
|
||||
TestRoute(graph, {0, 0}, {0, 4}, 5, &expectedRoute);
|
||||
}
|
||||
} // namespace routing_test
|
|
@ -27,6 +27,7 @@ SOURCES += \
|
|||
async_router_test.cpp \
|
||||
cross_routing_tests.cpp \
|
||||
followed_polyline_test.cpp \
|
||||
index_graph_test.cpp \
|
||||
nearest_edge_finder_tests.cpp \
|
||||
online_cross_fetcher_test.cpp \
|
||||
osrm_router_test.cpp \
|
||||
|
|
225
routing/single_mwm_router.cpp
Normal file
225
routing/single_mwm_router.cpp
Normal file
|
@ -0,0 +1,225 @@
|
|||
#include "routing/single_mwm_router.hpp"
|
||||
|
||||
#include "routing/base/astar_algorithm.hpp"
|
||||
#include "routing/base/astar_progress.hpp"
|
||||
#include "routing/bicycle_directions.hpp"
|
||||
#include "routing/bicycle_model.hpp"
|
||||
#include "routing/car_model.hpp"
|
||||
#include "routing/index_graph.hpp"
|
||||
#include "routing/index_graph_starter.hpp"
|
||||
#include "routing/pedestrian_model.hpp"
|
||||
#include "routing/route.hpp"
|
||||
#include "routing/routing_helpers.hpp"
|
||||
#include "routing/turns_generator.hpp"
|
||||
|
||||
#include "indexer/feature_altitude.hpp"
|
||||
#include "indexer/routing_section.hpp"
|
||||
|
||||
#include "geometry/distance.hpp"
|
||||
#include "geometry/mercator.hpp"
|
||||
#include "geometry/point2d.hpp"
|
||||
|
||||
#include "base/exception.hpp"
|
||||
|
||||
using namespace routing;
|
||||
|
||||
namespace
|
||||
{
|
||||
size_t constexpr kMaxRoadCandidates = 6;
|
||||
float constexpr kProgressInterval = 2;
|
||||
uint32_t constexpr kDrawPointsPeriod = 10;
|
||||
|
||||
vector<Junction> ConvertToJunctions(IndexGraphStarter & starter, vector<Joint::Id> const & joints)
|
||||
{
|
||||
vector<RoadPoint> roadPoints;
|
||||
starter.RedressRoute(joints, roadPoints);
|
||||
|
||||
vector<Junction> junctions;
|
||||
junctions.reserve(roadPoints.size());
|
||||
|
||||
Geometry & geometry = starter.GetGraph().GetGeometry();
|
||||
// TODO: Use real altitudes for pedestrian and bicycle routing.
|
||||
for (RoadPoint const & point : roadPoints)
|
||||
junctions.emplace_back(geometry.GetPoint(point), feature::kDefaultAltitudeMeters);
|
||||
|
||||
return junctions;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace routing
|
||||
{
|
||||
SingleMwmRouter::SingleMwmRouter(string const & name, Index const & index,
|
||||
shared_ptr<VehicleModelFactory> vehicleModelFactory,
|
||||
shared_ptr<EdgeEstimator> estimator,
|
||||
unique_ptr<IDirectionsEngine> directionsEngine)
|
||||
: m_name(name)
|
||||
, m_index(index)
|
||||
, m_roadGraph(index, IRoadGraph::Mode::ObeyOnewayTag, vehicleModelFactory)
|
||||
, m_vehicleModelFactory(vehicleModelFactory)
|
||||
, m_estimator(estimator)
|
||||
, m_directionsEngine(move(directionsEngine))
|
||||
{
|
||||
ASSERT(!m_name.empty(), ());
|
||||
ASSERT(m_vehicleModelFactory, ());
|
||||
ASSERT(m_estimator, ());
|
||||
ASSERT(m_directionsEngine, ());
|
||||
}
|
||||
|
||||
IRouter::ResultCode SingleMwmRouter::CalculateRoute(MwmSet::MwmId const & mwmId,
|
||||
m2::PointD const & startPoint,
|
||||
m2::PointD const & startDirection,
|
||||
m2::PointD const & finalPoint,
|
||||
RouterDelegate const & delegate, Route & route)
|
||||
{
|
||||
try
|
||||
{
|
||||
return DoCalculateRoute(mwmId, startPoint, startDirection, finalPoint, delegate, route);
|
||||
}
|
||||
catch (RootException const & e)
|
||||
{
|
||||
LOG(LERROR, ("Can't find path from", MercatorBounds::ToLatLon(startPoint), "to",
|
||||
MercatorBounds::ToLatLon(finalPoint), ":\n ", e.what()));
|
||||
return IRouter::InternalError;
|
||||
}
|
||||
}
|
||||
|
||||
IRouter::ResultCode SingleMwmRouter::DoCalculateRoute(MwmSet::MwmId const & mwmId,
|
||||
m2::PointD const & startPoint,
|
||||
m2::PointD const & /* startDirection */,
|
||||
m2::PointD const & finalPoint,
|
||||
RouterDelegate const & delegate,
|
||||
Route & route)
|
||||
{
|
||||
if (!mwmId.IsAlive())
|
||||
return IRouter::RouteFileNotExist;
|
||||
|
||||
string const & country = mwmId.GetInfo()->GetCountryName();
|
||||
|
||||
Edge startEdge;
|
||||
if (!FindClosestEdge(mwmId, startPoint, startEdge))
|
||||
return IRouter::StartPointNotFound;
|
||||
|
||||
Edge finishEdge;
|
||||
if (!FindClosestEdge(mwmId, finalPoint, finishEdge))
|
||||
return IRouter::EndPointNotFound;
|
||||
|
||||
RoadPoint const start(startEdge.GetFeatureId().m_index, startEdge.GetSegId());
|
||||
RoadPoint const finish(finishEdge.GetFeatureId().m_index, finishEdge.GetSegId());
|
||||
|
||||
IndexGraph graph(GeometryLoader::Create(
|
||||
m_index, mwmId, m_vehicleModelFactory->GetVehicleModelForCountry(country)),
|
||||
m_estimator);
|
||||
|
||||
if (!LoadIndex(mwmId, country, graph))
|
||||
return IRouter::RouteFileNotExist;
|
||||
|
||||
IndexGraphStarter starter(graph, start, finish);
|
||||
|
||||
AStarProgress progress(0, 100);
|
||||
progress.Initialize(graph.GetGeometry().GetPoint(start), graph.GetGeometry().GetPoint(finish));
|
||||
|
||||
uint32_t drawPointsStep = 0;
|
||||
auto onVisitJunction = [&](Joint::Id const & from, Joint::Id const & to) {
|
||||
m2::PointD const & pointFrom = starter.GetPoint(from);
|
||||
m2::PointD const & pointTo = starter.GetPoint(to);
|
||||
auto const lastValue = progress.GetLastValue();
|
||||
auto const newValue = progress.GetProgressForBidirectedAlgo(pointFrom, pointTo);
|
||||
if (newValue - lastValue > kProgressInterval)
|
||||
delegate.OnProgress(newValue);
|
||||
if (drawPointsStep % kDrawPointsPeriod == 0)
|
||||
delegate.OnPointCheck(pointFrom);
|
||||
++drawPointsStep;
|
||||
};
|
||||
|
||||
AStarAlgorithm<IndexGraphStarter> algorithm;
|
||||
|
||||
RoutingResult<Joint::Id> routingResult;
|
||||
auto const resultCode =
|
||||
algorithm.FindPathBidirectional(starter, starter.GetStartJoint(), starter.GetFinishJoint(),
|
||||
routingResult, delegate, onVisitJunction);
|
||||
|
||||
switch (resultCode)
|
||||
{
|
||||
case AStarAlgorithm<IndexGraphStarter>::Result::NoPath: return IRouter::RouteNotFound;
|
||||
case AStarAlgorithm<IndexGraphStarter>::Result::Cancelled: return IRouter::Cancelled;
|
||||
case AStarAlgorithm<IndexGraphStarter>::Result::OK:
|
||||
vector<Junction> path = ConvertToJunctions(starter, routingResult.path);
|
||||
ReconstructRoute(m_directionsEngine.get(), m_roadGraph, delegate, path, route);
|
||||
return IRouter::NoError;
|
||||
}
|
||||
}
|
||||
|
||||
bool SingleMwmRouter::FindClosestEdge(MwmSet::MwmId const & mwmId, m2::PointD const & point,
|
||||
Edge & closestEdge) const
|
||||
{
|
||||
vector<pair<Edge, Junction>> candidates;
|
||||
m_roadGraph.FindClosestEdges(point, kMaxRoadCandidates, candidates);
|
||||
|
||||
double minDistance = numeric_limits<double>::max();
|
||||
size_t minIndex = candidates.size();
|
||||
|
||||
for (size_t i = 0; i < candidates.size(); ++i)
|
||||
{
|
||||
Edge const & edge = candidates[i].first;
|
||||
if (edge.GetFeatureId().m_mwmId != mwmId)
|
||||
continue;
|
||||
|
||||
m2::DistanceToLineSquare<m2::PointD> squaredDistance;
|
||||
squaredDistance.SetBounds(edge.GetStartJunction().GetPoint(), edge.GetEndJunction().GetPoint());
|
||||
double const distance = squaredDistance(point);
|
||||
if (distance < minDistance)
|
||||
{
|
||||
minDistance = distance;
|
||||
minIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (minIndex == candidates.size())
|
||||
return false;
|
||||
|
||||
closestEdge = candidates[minIndex].first;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SingleMwmRouter::LoadIndex(MwmSet::MwmId const & mwmId, string const & country,
|
||||
IndexGraph & graph)
|
||||
{
|
||||
MwmSet::MwmHandle mwmHandle = m_index.GetMwmHandleById(mwmId);
|
||||
if (!mwmHandle.IsAlive())
|
||||
return false;
|
||||
|
||||
MwmValue const * mwmValue = mwmHandle.GetValue<MwmValue>();
|
||||
try
|
||||
{
|
||||
my::Timer timer;
|
||||
FilesContainerR::TReader reader(mwmValue->m_cont.GetReader(ROUTING_FILE_TAG));
|
||||
ReaderSource<FilesContainerR::TReader> src(reader);
|
||||
feature::RoutingSectionHeader header;
|
||||
header.Deserialize(src);
|
||||
graph.Deserialize(src);
|
||||
LOG(LINFO,
|
||||
(ROUTING_FILE_TAG, "section for", country, "loaded in", timer.ElapsedSeconds(), "seconds"));
|
||||
return true;
|
||||
}
|
||||
catch (Reader::OpenException const & e)
|
||||
{
|
||||
LOG(LERROR, ("File", mwmValue->GetCountryFileName(), "Error while reading", ROUTING_FILE_TAG,
|
||||
"section:", e.Msg()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
unique_ptr<SingleMwmRouter> SingleMwmRouter::CreateCarRouter(Index const & index)
|
||||
{
|
||||
auto vehicleModelFactory = make_shared<CarModelFactory>();
|
||||
// @TODO Bicycle turn generation engine is used now. It's ok for the time being.
|
||||
// But later a special car turn generation engine should be implemented.
|
||||
auto directionsEngine = make_unique<BicycleDirectionsEngine>(index);
|
||||
auto estimator = EdgeEstimator::CreateForCar(*vehicleModelFactory->GetVehicleModel());
|
||||
auto router =
|
||||
make_unique<SingleMwmRouter>("astar-bidirectional-car", index, move(vehicleModelFactory),
|
||||
estimator, move(directionsEngine));
|
||||
return router;
|
||||
}
|
||||
} // namespace routing
|
52
routing/single_mwm_router.hpp
Normal file
52
routing/single_mwm_router.hpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
#pragma once
|
||||
|
||||
#include "routing/directions_engine.hpp"
|
||||
#include "routing/edge_estimator.hpp"
|
||||
#include "routing/features_road_graph.hpp"
|
||||
#include "routing/router.hpp"
|
||||
#include "routing/vehicle_model.hpp"
|
||||
|
||||
#include "indexer/index.hpp"
|
||||
|
||||
#include "std/shared_ptr.hpp"
|
||||
#include "std/unique_ptr.hpp"
|
||||
#include "std/vector.hpp"
|
||||
|
||||
namespace routing
|
||||
{
|
||||
class IndexGraph;
|
||||
|
||||
class SingleMwmRouter
|
||||
{
|
||||
public:
|
||||
SingleMwmRouter(string const & name, Index const & index,
|
||||
shared_ptr<VehicleModelFactory> vehicleModelFactory,
|
||||
shared_ptr<EdgeEstimator> estimator,
|
||||
unique_ptr<IDirectionsEngine> directionsEngine);
|
||||
|
||||
string const & GetName() const { return m_name; }
|
||||
|
||||
IRouter::ResultCode CalculateRoute(MwmSet::MwmId const & mwmId, m2::PointD const & startPoint,
|
||||
m2::PointD const & startDirection,
|
||||
m2::PointD const & finalPoint, RouterDelegate const & delegate,
|
||||
Route & route);
|
||||
|
||||
static unique_ptr<SingleMwmRouter> CreateCarRouter(Index const & index);
|
||||
|
||||
private:
|
||||
IRouter::ResultCode DoCalculateRoute(MwmSet::MwmId const & mwmId, m2::PointD const & startPoint,
|
||||
m2::PointD const & startDirection,
|
||||
m2::PointD const & finalPoint,
|
||||
RouterDelegate const & delegate, Route & route);
|
||||
bool FindClosestEdge(MwmSet::MwmId const & mwmId, m2::PointD const & point,
|
||||
Edge & closestEdge) const;
|
||||
bool LoadIndex(MwmSet::MwmId const & mwmId, string const & country, IndexGraph & graph);
|
||||
|
||||
string const m_name;
|
||||
Index const & m_index;
|
||||
FeaturesRoadGraph m_roadGraph;
|
||||
shared_ptr<VehicleModelFactory> m_vehicleModelFactory;
|
||||
shared_ptr<EdgeEstimator> m_estimator;
|
||||
unique_ptr<IDirectionsEngine> m_directionsEngine;
|
||||
};
|
||||
} // namespace routing
|
|
@ -7,6 +7,8 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
0C5FEC701DDE19E50017688C /* routing_index_generator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C5FEC6E1DDE19E50017688C /* routing_index_generator.cpp */; };
|
||||
0C5FEC711DDE19E50017688C /* routing_index_generator.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0C5FEC6F1DDE19E50017688C /* routing_index_generator.hpp */; };
|
||||
34F558791DBF4C7800A4FC11 /* booking_quality_check.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 34F558771DBF4C7800A4FC11 /* booking_quality_check.cpp */; };
|
||||
34F5587B1DBF4C8300A4FC11 /* feature_segments_checker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 34F5587A1DBF4C8300A4FC11 /* feature_segments_checker.cpp */; };
|
||||
34F558871DBF4C9600A4FC11 /* opentable_dataset.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 34F5587E1DBF4C9600A4FC11 /* opentable_dataset.cpp */; };
|
||||
|
@ -86,6 +88,8 @@
|
|||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0C5FEC6E1DDE19E50017688C /* routing_index_generator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = routing_index_generator.cpp; sourceTree = "<group>"; };
|
||||
0C5FEC6F1DDE19E50017688C /* routing_index_generator.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = routing_index_generator.hpp; sourceTree = "<group>"; };
|
||||
34AF87CF1DBE52DC00E5E7DC /* common-debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "common-debug.xcconfig"; path = "../common-debug.xcconfig"; sourceTree = "<group>"; };
|
||||
34AF87D01DBE52DC00E5E7DC /* common-release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "common-release.xcconfig"; path = "../common-release.xcconfig"; sourceTree = "<group>"; };
|
||||
34F558771DBF4C7800A4FC11 /* booking_quality_check.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = booking_quality_check.cpp; path = booking_quality_check/booking_quality_check.cpp; sourceTree = "<group>"; };
|
||||
|
@ -269,6 +273,8 @@
|
|||
6753404D1A3F2A7400A0A8C3 /* polygonizer.hpp */,
|
||||
6753404E1A3F2A7400A0A8C3 /* routing_generator.cpp */,
|
||||
6753404F1A3F2A7400A0A8C3 /* routing_generator.hpp */,
|
||||
0C5FEC6E1DDE19E50017688C /* routing_index_generator.cpp */,
|
||||
0C5FEC6F1DDE19E50017688C /* routing_index_generator.hpp */,
|
||||
675340501A3F2A7400A0A8C3 /* statistics.cpp */,
|
||||
675340511A3F2A7400A0A8C3 /* statistics.hpp */,
|
||||
675340521A3F2A7400A0A8C3 /* tesselator.cpp */,
|
||||
|
@ -331,6 +337,7 @@
|
|||
34F5588B1DBF4C9600A4FC11 /* sponsored_dataset.hpp in Headers */,
|
||||
6753405F1A3F2A7400A0A8C3 /* borders_loader.hpp in Headers */,
|
||||
675340801A3F2A7400A0A8C3 /* polygonizer.hpp in Headers */,
|
||||
0C5FEC711DDE19E50017688C /* routing_index_generator.hpp in Headers */,
|
||||
675340941C5231BA002CF0D9 /* search_index_builder.hpp in Headers */,
|
||||
3D51BC591D5E512500F1FA8D /* srtm_parser.hpp in Headers */,
|
||||
677E2A181CAACC5F001DC42A /* towns_dumper.hpp in Headers */,
|
||||
|
@ -438,6 +445,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
6753406C1A3F2A7400A0A8C3 /* feature_generator.cpp in Sources */,
|
||||
0C5FEC701DDE19E50017688C /* routing_index_generator.cpp in Sources */,
|
||||
3D51BC561D5E512500F1FA8D /* region_meta.cpp in Sources */,
|
||||
3D51BC521D5E512500F1FA8D /* altitude_generator.cpp in Sources */,
|
||||
3D51BC581D5E512500F1FA8D /* srtm_parser.cpp in Sources */,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
0C5FEC731DDE1A140017688C /* routing_section.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0C5FEC721DDE1A140017688C /* routing_section.hpp */; };
|
||||
340DF9D01C1FF04D00B5C7EC /* osm_editor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 340DF9CF1C1FF04D00B5C7EC /* osm_editor.cpp */; };
|
||||
34583BC71C88552100F94664 /* cuisines.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 34583BC11C88552100F94664 /* cuisines.cpp */; };
|
||||
34583BC81C88552100F94664 /* cuisines.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 34583BC21C88552100F94664 /* cuisines.hpp */; };
|
||||
|
@ -223,6 +224,7 @@
|
|||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0C5FEC721DDE1A140017688C /* routing_section.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = routing_section.hpp; sourceTree = "<group>"; };
|
||||
340DF9CF1C1FF04D00B5C7EC /* osm_editor.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = osm_editor.cpp; sourceTree = "<group>"; };
|
||||
34583BC11C88552100F94664 /* cuisines.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cuisines.cpp; sourceTree = "<group>"; };
|
||||
34583BC21C88552100F94664 /* cuisines.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = cuisines.hpp; sourceTree = "<group>"; };
|
||||
|
@ -651,6 +653,7 @@
|
|||
56C74C151C749E4700B71B9F /* displacement_manager.hpp */,
|
||||
56C74C161C749E4700B71B9F /* edits_migration.cpp */,
|
||||
56C74C171C749E4700B71B9F /* edits_migration.hpp */,
|
||||
0C5FEC721DDE1A140017688C /* routing_section.hpp */,
|
||||
56C74C181C749E4700B71B9F /* search_delimiters.cpp */,
|
||||
56C74C191C749E4700B71B9F /* search_delimiters.hpp */,
|
||||
56C74C1A1C749E4700B71B9F /* search_string_utils.cpp */,
|
||||
|
@ -822,6 +825,7 @@
|
|||
675341411A3F540F00A0A8C3 /* scales.hpp in Headers */,
|
||||
675341321A3F540F00A0A8C3 /* interval_index_builder.hpp in Headers */,
|
||||
347F337C1C454242009758CC /* rank_table.hpp in Headers */,
|
||||
0C5FEC731DDE1A140017688C /* routing_section.hpp in Headers */,
|
||||
6753414B1A3F540F00A0A8C3 /* tesselator_decl.hpp in Headers */,
|
||||
347F33801C454242009758CC /* trie_reader.hpp in Headers */,
|
||||
675341191A3F540F00A0A8C3 /* feature_decl.hpp in Headers */,
|
||||
|
|
|
@ -7,6 +7,26 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
0C0DF9211DE898B70055A22F /* index_graph_starter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C0DF91F1DE898B70055A22F /* index_graph_starter.cpp */; };
|
||||
0C0DF9221DE898B70055A22F /* index_graph_starter.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0C0DF9201DE898B70055A22F /* index_graph_starter.hpp */; };
|
||||
0C0DF9251DE898CF0055A22F /* single_mwm_router.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C0DF9231DE898CF0055A22F /* single_mwm_router.cpp */; };
|
||||
0C0DF9261DE898CF0055A22F /* single_mwm_router.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0C0DF9241DE898CF0055A22F /* single_mwm_router.hpp */; };
|
||||
0C0DF9291DE898FF0055A22F /* routing_exception.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0C0DF9271DE898FF0055A22F /* routing_exception.hpp */; };
|
||||
0C0DF92A1DE898FF0055A22F /* routing_helpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C0DF9281DE898FF0055A22F /* routing_helpers.cpp */; };
|
||||
0C5FEC541DDE191E0017688C /* edge_estimator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C5FEC521DDE191E0017688C /* edge_estimator.cpp */; };
|
||||
0C5FEC551DDE191E0017688C /* edge_estimator.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0C5FEC531DDE191E0017688C /* edge_estimator.hpp */; };
|
||||
0C5FEC5E1DDE192A0017688C /* geometry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C5FEC561DDE192A0017688C /* geometry.cpp */; };
|
||||
0C5FEC5F1DDE192A0017688C /* geometry.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0C5FEC571DDE192A0017688C /* geometry.hpp */; };
|
||||
0C5FEC601DDE192A0017688C /* index_graph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C5FEC581DDE192A0017688C /* index_graph.cpp */; };
|
||||
0C5FEC611DDE192A0017688C /* index_graph.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0C5FEC591DDE192A0017688C /* index_graph.hpp */; };
|
||||
0C5FEC621DDE192A0017688C /* joint_index.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C5FEC5A1DDE192A0017688C /* joint_index.cpp */; };
|
||||
0C5FEC631DDE192A0017688C /* joint_index.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0C5FEC5B1DDE192A0017688C /* joint_index.hpp */; };
|
||||
0C5FEC641DDE192A0017688C /* joint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C5FEC5C1DDE192A0017688C /* joint.cpp */; };
|
||||
0C5FEC651DDE192A0017688C /* joint.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0C5FEC5D1DDE192A0017688C /* joint.hpp */; };
|
||||
0C5FEC691DDE193F0017688C /* road_index.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C5FEC661DDE193F0017688C /* road_index.cpp */; };
|
||||
0C5FEC6A1DDE193F0017688C /* road_index.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0C5FEC671DDE193F0017688C /* road_index.hpp */; };
|
||||
0C5FEC6B1DDE193F0017688C /* road_point.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0C5FEC681DDE193F0017688C /* road_point.hpp */; };
|
||||
0C5FEC6D1DDE19A40017688C /* index_graph_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C5FEC6C1DDE19A40017688C /* index_graph_test.cpp */; };
|
||||
3462FDAD1DC1E5BF00906FD7 /* libopening_hours.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3462FDAC1DC1E5BF00906FD7 /* libopening_hours.a */; };
|
||||
56099E291CC7C97D00A7772A /* loaded_path_segment.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 56099E251CC7C97D00A7772A /* loaded_path_segment.hpp */; };
|
||||
56099E2A1CC7C97D00A7772A /* routing_result_graph.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 56099E261CC7C97D00A7772A /* routing_result_graph.hpp */; };
|
||||
|
@ -219,6 +239,26 @@
|
|||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0C0DF91F1DE898B70055A22F /* index_graph_starter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = index_graph_starter.cpp; sourceTree = "<group>"; };
|
||||
0C0DF9201DE898B70055A22F /* index_graph_starter.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = index_graph_starter.hpp; sourceTree = "<group>"; };
|
||||
0C0DF9231DE898CF0055A22F /* single_mwm_router.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = single_mwm_router.cpp; sourceTree = "<group>"; };
|
||||
0C0DF9241DE898CF0055A22F /* single_mwm_router.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = single_mwm_router.hpp; sourceTree = "<group>"; };
|
||||
0C0DF9271DE898FF0055A22F /* routing_exception.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = routing_exception.hpp; sourceTree = "<group>"; };
|
||||
0C0DF9281DE898FF0055A22F /* routing_helpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = routing_helpers.cpp; sourceTree = "<group>"; };
|
||||
0C5FEC521DDE191E0017688C /* edge_estimator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = edge_estimator.cpp; sourceTree = "<group>"; };
|
||||
0C5FEC531DDE191E0017688C /* edge_estimator.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = edge_estimator.hpp; sourceTree = "<group>"; };
|
||||
0C5FEC561DDE192A0017688C /* geometry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = geometry.cpp; sourceTree = "<group>"; };
|
||||
0C5FEC571DDE192A0017688C /* geometry.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = geometry.hpp; sourceTree = "<group>"; };
|
||||
0C5FEC581DDE192A0017688C /* index_graph.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = index_graph.cpp; sourceTree = "<group>"; };
|
||||
0C5FEC591DDE192A0017688C /* index_graph.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = index_graph.hpp; sourceTree = "<group>"; };
|
||||
0C5FEC5A1DDE192A0017688C /* joint_index.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = joint_index.cpp; sourceTree = "<group>"; };
|
||||
0C5FEC5B1DDE192A0017688C /* joint_index.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = joint_index.hpp; sourceTree = "<group>"; };
|
||||
0C5FEC5C1DDE192A0017688C /* joint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = joint.cpp; sourceTree = "<group>"; };
|
||||
0C5FEC5D1DDE192A0017688C /* joint.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = joint.hpp; sourceTree = "<group>"; };
|
||||
0C5FEC661DDE193F0017688C /* road_index.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = road_index.cpp; sourceTree = "<group>"; };
|
||||
0C5FEC671DDE193F0017688C /* road_index.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = road_index.hpp; sourceTree = "<group>"; };
|
||||
0C5FEC681DDE193F0017688C /* road_point.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = road_point.hpp; sourceTree = "<group>"; };
|
||||
0C5FEC6C1DDE19A40017688C /* index_graph_test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = index_graph_test.cpp; sourceTree = "<group>"; };
|
||||
3462FDAC1DC1E5BF00906FD7 /* libopening_hours.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libopening_hours.a; path = "../../../omim-build/xcode/Debug/libopening_hours.a"; sourceTree = "<group>"; };
|
||||
34F558351DBF2A2600A4FC11 /* common-debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "common-debug.xcconfig"; path = "../common-debug.xcconfig"; sourceTree = "<group>"; };
|
||||
34F558361DBF2A2600A4FC11 /* common-release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "common-release.xcconfig"; path = "../common-release.xcconfig"; sourceTree = "<group>"; };
|
||||
|
@ -506,6 +546,7 @@
|
|||
6742ACA91C68A0B1009CB89E /* async_router_test.cpp */,
|
||||
6742ACAA1C68A0B1009CB89E /* cross_routing_tests.cpp */,
|
||||
6742ACAB1C68A0B1009CB89E /* followed_polyline_test.cpp */,
|
||||
0C5FEC6C1DDE19A40017688C /* index_graph_test.cpp */,
|
||||
6742ACAC1C68A0B1009CB89E /* nearest_edge_finder_tests.cpp */,
|
||||
6742ACAD1C68A0B1009CB89E /* online_cross_fetcher_test.cpp */,
|
||||
6742ACAE1C68A0B1009CB89E /* osrm_router_test.cpp */,
|
||||
|
@ -622,8 +663,20 @@
|
|||
675343FA1A3F640D00A0A8C3 /* routing */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0C5FEC521DDE191E0017688C /* edge_estimator.cpp */,
|
||||
0C5FEC531DDE191E0017688C /* edge_estimator.hpp */,
|
||||
56EA2FD41D8FD8590083F01A /* routing_helpers.hpp */,
|
||||
56099E2C1CC8FBDA00A7772A /* osrm_path_segment_factory.cpp */,
|
||||
0C5FEC561DDE192A0017688C /* geometry.cpp */,
|
||||
0C5FEC571DDE192A0017688C /* geometry.hpp */,
|
||||
0C5FEC581DDE192A0017688C /* index_graph.cpp */,
|
||||
0C5FEC591DDE192A0017688C /* index_graph.hpp */,
|
||||
0C5FEC5A1DDE192A0017688C /* joint_index.cpp */,
|
||||
0C5FEC5B1DDE192A0017688C /* joint_index.hpp */,
|
||||
0C0DF91F1DE898B70055A22F /* index_graph_starter.cpp */,
|
||||
0C0DF9201DE898B70055A22F /* index_graph_starter.hpp */,
|
||||
0C5FEC5C1DDE192A0017688C /* joint.cpp */,
|
||||
0C5FEC5D1DDE192A0017688C /* joint.hpp */,
|
||||
56099E2D1CC8FBDA00A7772A /* osrm_path_segment_factory.hpp */,
|
||||
56826BCE1DB51C4E00807C62 /* car_router.cpp */,
|
||||
56826BCF1DB51C4E00807C62 /* car_router.hpp */,
|
||||
|
@ -637,6 +690,13 @@
|
|||
563B91C41CC4F1DC00222BC1 /* bicycle_model.hpp */,
|
||||
A17B42961BCFBD0E00A1EAE4 /* osrm_helpers.cpp */,
|
||||
A17B42971BCFBD0E00A1EAE4 /* osrm_helpers.hpp */,
|
||||
0C5FEC661DDE193F0017688C /* road_index.cpp */,
|
||||
0C5FEC671DDE193F0017688C /* road_index.hpp */,
|
||||
0C5FEC681DDE193F0017688C /* road_point.hpp */,
|
||||
0C0DF9271DE898FF0055A22F /* routing_exception.hpp */,
|
||||
0C0DF9281DE898FF0055A22F /* routing_helpers.cpp */,
|
||||
0C0DF9231DE898CF0055A22F /* single_mwm_router.cpp */,
|
||||
0C0DF9241DE898CF0055A22F /* single_mwm_router.hpp */,
|
||||
6741AA9A1BF35331002C974C /* turns_notification_manager.cpp */,
|
||||
6741AA9B1BF35331002C974C /* turns_notification_manager.hpp */,
|
||||
A1876BC41BB19C4300C9C743 /* speed_camera.cpp */,
|
||||
|
@ -724,10 +784,12 @@
|
|||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0C5FEC631DDE192A0017688C /* joint_index.hpp in Headers */,
|
||||
67AB92E51B7B3E6E00AB5194 /* routing_mapping.hpp in Headers */,
|
||||
674F9BCB1B0A580E00704FFA /* async_router.hpp in Headers */,
|
||||
674F9BD11B0A580E00704FFA /* online_cross_fetcher.hpp in Headers */,
|
||||
A120B3531B4A7C1C002F3808 /* astar_algorithm.hpp in Headers */,
|
||||
0C5FEC5F1DDE192A0017688C /* geometry.hpp in Headers */,
|
||||
674A28B21B1605D2001A525C /* osrm_engine.hpp in Headers */,
|
||||
67AB92E71B7B3E6E00AB5194 /* turns_tts_text.hpp in Headers */,
|
||||
56099E2A1CC7C97D00A7772A /* routing_result_graph.hpp in Headers */,
|
||||
|
@ -735,12 +797,15 @@
|
|||
674F9BD31B0A580E00704FFA /* road_graph_router.hpp in Headers */,
|
||||
675344141A3F644F00A0A8C3 /* osrm_data_facade.hpp in Headers */,
|
||||
6753441F1A3F644F00A0A8C3 /* turns.hpp in Headers */,
|
||||
0C5FEC611DDE192A0017688C /* index_graph.hpp in Headers */,
|
||||
6753441A1A3F644F00A0A8C3 /* osrm2feature_map.hpp in Headers */,
|
||||
6741AA9D1BF35331002C974C /* turns_notification_manager.hpp in Headers */,
|
||||
674F9BD71B0A580E00704FFA /* turns_generator.hpp in Headers */,
|
||||
0C0DF9261DE898CF0055A22F /* single_mwm_router.hpp in Headers */,
|
||||
A120B3461B4A7BE5002F3808 /* cross_mwm_road_graph.hpp in Headers */,
|
||||
6753441C1A3F644F00A0A8C3 /* route.hpp in Headers */,
|
||||
A1616E2C1B6B60AB003F078E /* router_delegate.hpp in Headers */,
|
||||
0C0DF9291DE898FF0055A22F /* routing_exception.hpp in Headers */,
|
||||
A17B42991BCFBD0E00A1EAE4 /* osrm_helpers.hpp in Headers */,
|
||||
67C7D42E1B4EB48F00FE41AA /* turns_sound_settings.hpp in Headers */,
|
||||
56099E341CC9247E00A7772A /* bicycle_directions.hpp in Headers */,
|
||||
|
@ -749,6 +814,7 @@
|
|||
670EE55F1B6001E7001E8064 /* routing_settings.hpp in Headers */,
|
||||
671F58BE1B874EC80032311E /* followed_polyline.hpp in Headers */,
|
||||
67C7D42C1B4EB48F00FE41AA /* pedestrian_model.hpp in Headers */,
|
||||
0C5FEC6A1DDE193F0017688C /* road_index.hpp in Headers */,
|
||||
674F9BCD1B0A580E00704FFA /* features_road_graph.hpp in Headers */,
|
||||
670EE5741B664796001E8064 /* pedestrian_directions.hpp in Headers */,
|
||||
6753441D1A3F644F00A0A8C3 /* router.hpp in Headers */,
|
||||
|
@ -756,6 +822,7 @@
|
|||
670EE5721B664796001E8064 /* directions_engine.hpp in Headers */,
|
||||
A1876BC71BB19C4300C9C743 /* speed_camera.hpp in Headers */,
|
||||
56EA2FD51D8FD8590083F01A /* routing_helpers.hpp in Headers */,
|
||||
0C0DF9221DE898B70055A22F /* index_graph_starter.hpp in Headers */,
|
||||
56099E2F1CC8FBDA00A7772A /* osrm_path_segment_factory.hpp in Headers */,
|
||||
67C7D42A1B4EB48F00FE41AA /* car_model.hpp in Headers */,
|
||||
670D049F1B0B4A970013A7AC /* nearest_edge_finder.hpp in Headers */,
|
||||
|
@ -763,10 +830,13 @@
|
|||
674F9BD51B0A580E00704FFA /* road_graph.hpp in Headers */,
|
||||
56826BD11DB51C4E00807C62 /* car_router.hpp in Headers */,
|
||||
A120B3511B4A7C0A002F3808 /* routing_algorithm.hpp in Headers */,
|
||||
0C5FEC6B1DDE193F0017688C /* road_point.hpp in Headers */,
|
||||
675344211A3F644F00A0A8C3 /* vehicle_model.hpp in Headers */,
|
||||
56099E2B1CC7C97D00A7772A /* turn_candidate.hpp in Headers */,
|
||||
0C5FEC551DDE191E0017688C /* edge_estimator.hpp in Headers */,
|
||||
670B84C11A9381D900CE4492 /* cross_routing_context.hpp in Headers */,
|
||||
563B91C61CC4F1DC00222BC1 /* bicycle_model.hpp in Headers */,
|
||||
0C5FEC651DDE192A0017688C /* joint.hpp in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -983,6 +1053,7 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0C5FEC641DDE192A0017688C /* joint.cpp in Sources */,
|
||||
56826BD01DB51C4E00807C62 /* car_router.cpp in Sources */,
|
||||
56099E2E1CC8FBDA00A7772A /* osrm_path_segment_factory.cpp in Sources */,
|
||||
675344201A3F644F00A0A8C3 /* vehicle_model.cpp in Sources */,
|
||||
|
@ -990,6 +1061,8 @@
|
|||
A1616E2B1B6B60AB003F078E /* router_delegate.cpp in Sources */,
|
||||
6741AA9C1BF35331002C974C /* turns_notification_manager.cpp in Sources */,
|
||||
67C7D42B1B4EB48F00FE41AA /* pedestrian_model.cpp in Sources */,
|
||||
0C0DF9251DE898CF0055A22F /* single_mwm_router.cpp in Sources */,
|
||||
0C0DF9211DE898B70055A22F /* index_graph_starter.cpp in Sources */,
|
||||
A120B3471B4A7BE5002F3808 /* cross_mwm_router.cpp in Sources */,
|
||||
670EE5731B664796001E8064 /* pedestrian_directions.cpp in Sources */,
|
||||
6753441B1A3F644F00A0A8C3 /* route.cpp in Sources */,
|
||||
|
@ -1001,6 +1074,7 @@
|
|||
563B91C51CC4F1DC00222BC1 /* bicycle_model.cpp in Sources */,
|
||||
674F9BD21B0A580E00704FFA /* road_graph_router.cpp in Sources */,
|
||||
A1876BC61BB19C4300C9C743 /* speed_camera.cpp in Sources */,
|
||||
0C5FEC691DDE193F0017688C /* road_index.cpp in Sources */,
|
||||
671F58BD1B874EC80032311E /* followed_polyline.cpp in Sources */,
|
||||
670EE55D1B6001E7001E8064 /* routing_session.cpp in Sources */,
|
||||
A120B3451B4A7BE5002F3808 /* cross_mwm_road_graph.cpp in Sources */,
|
||||
|
@ -1008,15 +1082,21 @@
|
|||
56099E331CC9247E00A7772A /* bicycle_directions.cpp in Sources */,
|
||||
674A28B11B1605D2001A525C /* osrm_engine.cpp in Sources */,
|
||||
674F9BD41B0A580E00704FFA /* road_graph.cpp in Sources */,
|
||||
0C0DF92A1DE898FF0055A22F /* routing_helpers.cpp in Sources */,
|
||||
67AB92E61B7B3E6E00AB5194 /* turns_tts_text.cpp in Sources */,
|
||||
0C5FEC601DDE192A0017688C /* index_graph.cpp in Sources */,
|
||||
0C5FEC6D1DDE19A40017688C /* index_graph_test.cpp in Sources */,
|
||||
6753441E1A3F644F00A0A8C3 /* turns.cpp in Sources */,
|
||||
670B84C01A9381D900CE4492 /* cross_routing_context.cpp in Sources */,
|
||||
A120B3501B4A7C0A002F3808 /* routing_algorithm.cpp in Sources */,
|
||||
674F9BCC1B0A580E00704FFA /* features_road_graph.cpp in Sources */,
|
||||
0C5FEC5E1DDE192A0017688C /* geometry.cpp in Sources */,
|
||||
674F9BD01B0A580E00704FFA /* online_cross_fetcher.cpp in Sources */,
|
||||
670EE5751B664796001E8064 /* router.cpp in Sources */,
|
||||
0C5FEC621DDE192A0017688C /* joint_index.cpp in Sources */,
|
||||
670C62131AC5A15700C38A8C /* routing_mapping.cpp in Sources */,
|
||||
67C7D42D1B4EB48F00FE41AA /* turns_sound_settings.cpp in Sources */,
|
||||
0C5FEC541DDE191E0017688C /* edge_estimator.cpp in Sources */,
|
||||
A120B34E1B4A7C0A002F3808 /* online_absent_fetcher.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
Loading…
Add table
Reference in a new issue