110 const V* defaultVehicle,
const std::string& outfile,
const int maxNumThreads,
M* mapMatcher) {
112 std::map<std::string, int> numericID;
113 bool haveTaz =
false;
115 if (!e->isInternal()) {
119 if (e->isTazConnector()) {
126 zstr::ifstream strm(filename.c_str(), std::fstream::in | std::fstream::binary);
128 std::ifstream strm(filename.c_str());
131 throw ProcessError(
TLF(
"Could not load landmark-lookup-table from '%'.", filename));
134 std::vector<const E*> landmarks;
135 int numLandMarks = 0;
136 bool haveData =
false;
137 while (std::getline(strm, line)) {
142 if (st.
size() == 1) {
143 const std::string lm = st.
get(0);
148 const auto& it = numericID.find(lm);
149 if (it == numericID.end()) {
150 throw ProcessError(
TLF(
"Landmark edge '%' does not exist in the network.", lm));
156 }
else if (st.
size() == 2) {
159 std::string lonStr = st.
get(0);
160 if (!lonStr.empty() && lonStr.back() ==
',') {
162 lonStr = lonStr.substr(0, lonStr.size() - 1);
166 std::vector<const E*> mapped;
169 if (mapped.size() != 1) {
170 throw ProcessError(
TLF(
"Invalid coordinate in landmark file, could not find edge at '%'", line));
172 std::string lm = mapped.front()->getID();
173 const auto& it = numericID.find(lm);
174 if (it == numericID.end()) {
175 throw ProcessError(
TLF(
"Landmark edge '%' does not exist in the network.", lm));
182 throw ProcessError(
TLF(
"Broken landmark file, could not parse '%' as coordinates.", line));
184 }
else if (st.
size() == 4) {
186 const std::string lm = st.
get(0);
187 const std::string edge = st.
get(1);
189 throw ProcessError(
TLF(
"Unknown or unordered edge '%' in landmark file.", edge));
197 const std::string edge = st.
get(0);
198 if ((
int)st.
size() != 2 * numLandMarks + 1) {
199 throw ProcessError(
TLF(
"Broken landmark file, unexpected number of entries (%) for edge '%'.", st.
size() - 1, edge));
202 throw ProcessError(
TLF(
"Unknown or unordered edge '%' in landmark file.", edge));
204 for (
int i = 0; i < numLandMarks; i++) {
214 WRITE_WARNINGF(
"No landmarks in '%', falling back to standard A*.", filename);
219 std::vector<RoutingTask*> currentTasks;
224 for (
int i = 0; i < numLandMarks; ++i) {
226 const E*
const landmark = landmarks[i];
229 WRITE_WARNINGF(
TL(
"No lookup table for landmark edge '%', recalculating."), landmark->getID());
231 const std::string tazWarning = haveTaz ?
" Make sure that any used taz or junction-taz definitions are loaded when generating the table" :
"";
232 throw ProcessError(
TLF(
"Not all network edges were found in the lookup table '%' for landmark edge '%'.%", filename, landmark->getID(), tazWarning));
236 if (maxNumThreads > 0) {
237 const double lmCost = router->
recomputeCosts({landmark}, defaultVehicle, 0);
239 if (threadPool.
size() == 0) {
240 if (reverseRouter ==
nullptr) {
243 std::vector<const E*> route;
244 router->
compute(landmark, landmark, defaultVehicle, 0, route,
true);
246 reverseRouter->setAutoBulkMode(
true);
248 while ((
int)threadPool.
size() < maxNumThreads) {
249 auto revClone = reverseRouter ==
nullptr ? nullptr : reverseRouter->clone();
250 new WorkerThread(threadPool, router->
clone(), revClone, defaultVehicle);
254 const E*
const edge = edges[j];
255 if (landmark != edge) {
256 const double sourceDestCost = lmCost + router->
recomputeCosts({edge}, defaultVehicle, 0);
257 currentTasks.push_back(
new RoutingTask(landmark, edge, sourceDestCost));
258 threadPool.
add(currentTasks.back(), i % maxNumThreads);
271 for (
int i = 0; i < numLandMarks; ++i) {
273 const E* landmark = landmarks[i];
274 const double lmCost = router->
recomputeCosts({landmark}, defaultVehicle, 0);
275 int unreachableFrom = 0;
276 int unreachableTo = 0;
278 const E*
const edge = edges[j];
279 double distFrom = -1;
281 if (landmark == edge) {
285 if (maxNumThreads > 0) {
287 distFrom = currentTasks[taskIndex]->getFromCost();
288 distTo = currentTasks[taskIndex]->getToCost();
289 delete currentTasks[taskIndex++];
292 const double sourceDestCost = lmCost + router->
recomputeCosts({edge}, defaultVehicle, 0);
293 std::vector<const E*> route;
294 std::vector<const ReversedEdge<E, V>*> reversedRoute;
296 if (edge->getPredecessors().size() > 0 && landmark->getSuccessors().size() > 0) {
297 if (router->
compute(landmark, edge, defaultVehicle, 0, route,
true)) {
298 distFrom =
MAX2(0.0, router->
recomputeCosts(route, defaultVehicle, 0) - sourceDestCost);
303 if (landmark->getPredecessors().size() > 0 && edge->getSuccessors().size() > 0) {
304 if (router->
compute(edge, landmark, defaultVehicle, 0, route,
true)) {
305 distTo =
MAX2(0.0, router->
recomputeCosts(route, defaultVehicle, 0) - sourceDestCost);
313 if (!edge->isTazConnector()) {
314 if (distFrom == -1) {
322 if (unreachableFrom > 0 || unreachableTo > 0) {
323 WRITE_WARNINGF(
TL(
"Landmark % is not reachable from % edges and is unable to reach % out of % total edges."),
324 landmark->getID(), unreachableFrom, unreachableTo, numericID.size());
328 if (!outfile.empty()) {
329 std::ostream* ostrm =
nullptr;
335 ostrm =
new std::ofstream(outfile.c_str());
339 if (!ostrm->good()) {
341 throw ProcessError(
TLF(
"Could not open file '%' for writing.", outfile));
344 for (
int i = 0; i < numLandMarks; ++i) {
349 for (
int i = 0; i < numLandMarks; ++i) {