108 const V* defaultVehicle,
const std::string& outfile,
const int maxNumThreads) {
110 std::map<std::string, int> numericID;
112 if (!e->isInternal()) {
120 zstr::ifstream strm(filename.c_str(), std::fstream::in | std::fstream::binary);
122 std::ifstream strm(filename.c_str());
125 throw ProcessError(
TLF(
"Could not load landmark-lookup-table from '%'.", filename));
128 std::vector<const E*> landmarks;
129 int numLandMarks = 0;
130 bool haveData =
false;
131 while (std::getline(strm, line)) {
136 if (st.
size() == 1) {
137 const std::string lm = st.
get(0);
142 const auto& it = numericID.find(lm);
143 if (it == numericID.end()) {
144 throw ProcessError(
TLF(
"Landmark edge '%' does not exist in the network.", lm));
150 }
else if (st.
size() == 4) {
152 const std::string lm = st.
get(0);
153 const std::string edge = st.
get(1);
155 throw ProcessError(
TLF(
"Unknown or unordered edge '%' in landmark file.", edge));
163 const std::string edge = st.
get(0);
164 if ((
int)st.
size() != 2 * numLandMarks + 1) {
165 throw ProcessError(
TLF(
"Broken landmark file, unexpected number of entries (%) for edge '%'.", st.
size() - 1, edge));
168 throw ProcessError(
TLF(
"Unknown or unordered edge '%' in landmark file.", edge));
170 for (
int i = 0; i < numLandMarks; i++) {
180 WRITE_WARNINGF(
"No landmarks in '%', falling back to standard A*.", filename);
185 std::vector<RoutingTask*> currentTasks;
190 for (
int i = 0; i < numLandMarks; ++i) {
192 const E*
const landmark = landmarks[i];
195 WRITE_WARNINGF(
TL(
"No lookup table for landmark edge '%', recalculating."), landmark->getID());
197 throw ProcessError(
TLF(
"Not all network edges were found in the lookup table '%' for landmark edge '%'.", filename, landmark->getID()));
201 if (maxNumThreads > 0) {
202 const double lmCost = router->
recomputeCosts({landmark}, defaultVehicle, 0);
204 if (threadPool.
size() == 0) {
205 if (reverseRouter ==
nullptr) {
208 std::vector<const E*> route;
209 router->
compute(landmark, landmark, defaultVehicle, 0, route);
211 reverseRouter->setAutoBulkMode(
true);
213 while ((
int)threadPool.
size() < maxNumThreads) {
214 auto revClone = reverseRouter ==
nullptr ? nullptr : reverseRouter->clone();
215 new WorkerThread(threadPool, router->
clone(), revClone, defaultVehicle);
219 const E*
const edge = edges[j];
220 if (landmark != edge) {
221 const double sourceDestCost = lmCost + router->
recomputeCosts({edge}, defaultVehicle, 0);
222 currentTasks.push_back(
new RoutingTask(landmark, edge, sourceDestCost));
223 threadPool.
add(currentTasks.back(), i % maxNumThreads);
236 for (
int i = 0; i < numLandMarks; ++i) {
238 const E* landmark = landmarks[i];
239 const double lmCost = router->
recomputeCosts({landmark}, defaultVehicle, 0);
241 const E* edge = edges[j];
242 double distFrom = -1;
244 if (landmark == edge) {
248 if (maxNumThreads > 0) {
250 distFrom = currentTasks[taskIndex]->getFromCost();
251 distTo = currentTasks[taskIndex]->getToCost();
252 delete currentTasks[taskIndex++];
255 const double sourceDestCost = lmCost + router->
recomputeCosts({edge}, defaultVehicle, 0);
256 std::vector<const E*> route;
257 std::vector<const ReversedEdge<E, V>*> reversedRoute;
259 if (edge->getPredecessors().size() > 0 && landmark->getSuccessors().size() > 0) {
260 if (router->
compute(landmark, edge, defaultVehicle, 0, route)) {
261 distFrom =
MAX2(0.0, router->
recomputeCosts(route, defaultVehicle, 0) - sourceDestCost);
266 if (landmark->getPredecessors().size() > 0 && edge->getSuccessors().size() > 0) {
267 if (router->
compute(edge, landmark, defaultVehicle, 0, route)) {
268 distTo =
MAX2(0.0, router->
recomputeCosts(route, defaultVehicle, 0) - sourceDestCost);
279 if (!outfile.empty()) {
280 std::ostream* ostrm =
nullptr;
286 ostrm =
new std::ofstream(outfile.c_str());
290 if (!ostrm->good()) {
292 throw ProcessError(
TLF(
"Could not open file '%' for writing.", outfile));
295 for (
int i = 0; i < numLandMarks; ++i) {
300 for (
int i = 0; i < numLandMarks; ++i) {
312 double lowerBound(
const E* from,
const E* to,
double speed,
double speedFactor,
double fromEffort,
double toEffort)
const {
313 double result = from->getDistanceTo(to) / speed;
314#ifdef ASTAR_DEBUG_LOOKUPTABLE
315 if (from->getID() == ASTAR_DEBUG_LOOKUPTABLE_FROM) {
316 std::cout <<
" lowerBound to=" << to->getID() <<
" result1=" << result <<
"\n";
319 for (
int i = 0; i < (int)
myLandmarks.size(); ++i) {
323 if (fl >= 0 && tl >= 0) {
324 const double bound = (fl - tl - toEffort) / speedFactor;
325#ifdef ASTAR_DEBUG_LOOKUPTABLE
326 if (from->getID() == ASTAR_DEBUG_LOOKUPTABLE_FROM && result < bound) {
327 std::cout <<
" landmarkTo=" <<
getLandmark(i) <<
" result2=" << bound
328 <<
" fl=" << fl <<
" tl=" << tl <<
"\n";
331 result =
MAX2(result, bound);
335 if (lt >= 0 && lf >= 0) {
336 const double bound = (lt - lf - fromEffort) / speedFactor;
337#ifdef ASTAR_DEBUG_LOOKUPTABLE
338 if (from->getID() == ASTAR_DEBUG_LOOKUPTABLE_FROM && result < bound) {
339 std::cout <<
" landmarkFrom=" <<
getLandmark(i) <<
" result3=" << bound
340 <<
" lt=" << lt <<
" lf=" << lf <<
"\n";
343 result =
MAX2(result, bound);
345 if ((tl >= 0 && fl < 0)
346 || (lf >= 0 && lt < 0)) {
348#ifdef ASTAR_DEBUG_UNREACHABLE
349 std::cout <<
" unreachable: from=" << from->getID() <<
" to=" << to->getID() <<
" landmark=" <<
getLandmark(i) <<
" "
350 << ((tl >= 0 && fl < 0) ?
" (toLandmark)" :
" (fromLandmark)")
351 <<
" fl=" << fl <<
" tl=" << tl <<
" lt=" << lt <<
" lf=" << lf