109 const V* defaultVehicle,
const std::string& outfile,
const int maxNumThreads,
M* mapMatcher) {
111 std::map<std::string, int> numericID;
113 if (!e->isInternal()) {
121 zstr::ifstream strm(filename.c_str(), std::fstream::in | std::fstream::binary);
123 std::ifstream strm(filename.c_str());
126 throw ProcessError(
TLF(
"Could not load landmark-lookup-table from '%'.", filename));
129 std::vector<const E*> landmarks;
130 int numLandMarks = 0;
131 bool haveData =
false;
132 while (std::getline(strm, line)) {
137 if (st.
size() == 1) {
138 const std::string lm = st.
get(0);
143 const auto& it = numericID.find(lm);
144 if (it == numericID.end()) {
145 throw ProcessError(
TLF(
"Landmark edge '%' does not exist in the network.", lm));
151 }
else if (st.
size() == 2) {
154 std::string lonStr = st.
get(0);
155 if (!lonStr.empty() && lonStr.back() ==
',') {
157 lonStr = lonStr.substr(0, lonStr.size() - 1);
161 std::vector<const E*> mapped;
164 if (mapped.size() != 1) {
165 throw ProcessError(
TLF(
"Invalid coordinate in landmark file, could not find edge at '%'", line));
167 std::string lm = mapped.front()->getID();
168 const auto& it = numericID.find(lm);
169 if (it == numericID.end()) {
170 throw ProcessError(
TLF(
"Landmark edge '%' does not exist in the network.", lm));
177 throw ProcessError(
TLF(
"Broken landmark file, could not parse '%' as coordinates.", line));
179 }
else if (st.
size() == 4) {
181 const std::string lm = st.
get(0);
182 const std::string edge = st.
get(1);
184 throw ProcessError(
TLF(
"Unknown or unordered edge '%' in landmark file.", edge));
192 const std::string edge = st.
get(0);
193 if ((
int)st.
size() != 2 * numLandMarks + 1) {
194 throw ProcessError(
TLF(
"Broken landmark file, unexpected number of entries (%) for edge '%'.", st.
size() - 1, edge));
197 throw ProcessError(
TLF(
"Unknown or unordered edge '%' in landmark file.", edge));
199 for (
int i = 0; i < numLandMarks; i++) {
209 WRITE_WARNINGF(
"No landmarks in '%', falling back to standard A*.", filename);
214 std::vector<RoutingTask*> currentTasks;
219 for (
int i = 0; i < numLandMarks; ++i) {
221 const E*
const landmark = landmarks[i];
224 WRITE_WARNINGF(
TL(
"No lookup table for landmark edge '%', recalculating."), landmark->getID());
226 throw ProcessError(
TLF(
"Not all network edges were found in the lookup table '%' for landmark edge '%'.", filename, landmark->getID()));
230 if (maxNumThreads > 0) {
231 const double lmCost = router->
recomputeCosts({landmark}, defaultVehicle, 0);
233 if (threadPool.
size() == 0) {
234 if (reverseRouter ==
nullptr) {
237 std::vector<const E*> route;
238 router->
compute(landmark, landmark, defaultVehicle, 0, route,
true);
240 reverseRouter->setAutoBulkMode(
true);
242 while ((
int)threadPool.
size() < maxNumThreads) {
243 auto revClone = reverseRouter ==
nullptr ? nullptr : reverseRouter->clone();
244 new WorkerThread(threadPool, router->
clone(), revClone, defaultVehicle);
248 const E*
const edge = edges[j];
249 if (landmark != edge) {
250 const double sourceDestCost = lmCost + router->
recomputeCosts({edge}, defaultVehicle, 0);
251 currentTasks.push_back(
new RoutingTask(landmark, edge, sourceDestCost));
252 threadPool.
add(currentTasks.back(), i % maxNumThreads);
265 for (
int i = 0; i < numLandMarks; ++i) {
267 const E* landmark = landmarks[i];
268 const double lmCost = router->
recomputeCosts({landmark}, defaultVehicle, 0);
269 int unreachableFrom = 0;
270 int unreachableTo = 0;
272 const E*
const edge = edges[j];
273 double distFrom = -1;
275 if (landmark == edge) {
279 if (maxNumThreads > 0) {
281 distFrom = currentTasks[taskIndex]->getFromCost();
282 distTo = currentTasks[taskIndex]->getToCost();
283 delete currentTasks[taskIndex++];
286 const double sourceDestCost = lmCost + router->
recomputeCosts({edge}, defaultVehicle, 0);
287 std::vector<const E*> route;
288 std::vector<const ReversedEdge<E, V>*> reversedRoute;
290 if (edge->getPredecessors().size() > 0 && landmark->getSuccessors().size() > 0) {
291 if (router->
compute(landmark, edge, defaultVehicle, 0, route,
true)) {
292 distFrom =
MAX2(0.0, router->
recomputeCosts(route, defaultVehicle, 0) - sourceDestCost);
297 if (landmark->getPredecessors().size() > 0 && edge->getSuccessors().size() > 0) {
298 if (router->
compute(edge, landmark, defaultVehicle, 0, route,
true)) {
299 distTo =
MAX2(0.0, router->
recomputeCosts(route, defaultVehicle, 0) - sourceDestCost);
307 if (!edge->isTazConnector()) {
308 if (distFrom == -1) {
316 if (unreachableFrom > 0 || unreachableTo > 0) {
317 WRITE_WARNINGF(
TL(
"Landmark % is not reachable from % edges and is unable to reach % out of % total edges."),
318 landmark->getID(), unreachableFrom, unreachableTo, numericID.size());
322 if (!outfile.empty()) {
323 std::ostream* ostrm =
nullptr;
329 ostrm =
new std::ofstream(outfile.c_str());
333 if (!ostrm->good()) {
335 throw ProcessError(
TLF(
"Could not open file '%' for writing.", outfile));
338 for (
int i = 0; i < numLandMarks; ++i) {
343 for (
int i = 0; i < numLandMarks; ++i) {