void MainWindow::generateRouteReport() { int totalCost = 0; QString route; // Check a route actually exists if (m_route.isEmpty() || !m_routeStart || !m_routeEnd) { postErrorMessage("Route has not been built."); return; } // Seed the route with the start node route = m_routeStart->text(); // Iterate over the route list updating the variables above QListIterator<EdgeItem*> i(m_route); while (i.hasNext()) { EdgeItem* edge = i.next(); // Add the target to the route route += edge->endNode()->text(); // Update the cost totalCost += edge->weight(); } // Print the result postInfoMessage(QString("Total route cost: %1").arg(totalCost)); postInfoMessage(QString("Route taken: %1").arg(route)); }
void MainWindow::routeNetwork() { // Storage class for the metadata required by Dijkstra struct MetaData { int distance; EdgeItem* edge; NodeItem* previous; NodeItem* owner; MetaData() : distance(INT_MAX) , edge(nullptr) , previous(nullptr) , owner(nullptr) { } MetaData(NodeItem* owner_) : distance(INT_MAX) , edge(nullptr) , previous(nullptr) , owner(owner_) { } }; QMap<NodeItem*, MetaData> metadata; QList<NodeItem*> nodes; NodeItem* current; // Initialise data-structres postInfoMessage("Preparing to route..."); { QMapIterator<QString, NodeItem*> i(m_graphNodes); while (i.hasNext()) { auto item = i.next(); // Initialise the metadata MetaData md(item.value()); if (item.value() == m_routeStart) { // Need minimal distance for the start node md.distance = 0; } metadata[i.value()] = md; // Initialise the node list nodes.append(i.value()); } } // Dijkstra's algorithm: calculate all the distances while (!nodes.isEmpty()) { // Find node with smallest distance { int d = INT_MAX; auto elem = nodes.end(); for (auto it = nodes.begin(); it != nodes.end(); ++it) { int thisDistance = metadata[*it].distance; if (thisDistance < d) { d = thisDistance; elem = it; } } current = *elem; // If we hit the target, we can stop if (current == m_routeEnd) { postInfoMessage("Search complete; reached target node!"); break; } else { // Emshrinken the list nodes.erase(elem); } } postInfoMessage(QString("Considering node %1...") .arg(current->text())); // Visit the neighbours QListIterator<EdgeItem*> i(current->edges()); while (i.hasNext()) { EdgeItem* edge = i.next(); NodeItem* neighbour = edge->endNode(); int dist = metadata[current].distance + edge->weight(); if (dist < metadata[neighbour].distance) { metadata[neighbour].distance = dist; metadata[neighbour].edge = edge; metadata[neighbour].previous = current; } } } // Walk backwards from the target to the source, building the path postInfoMessage("Back-tracking to construct route..."); for (current = m_routeEnd; current; current = metadata[current].previous) { EdgeItem* edge = metadata[current].edge; if (edge) { m_route.prepend(edge); } } // All done! postSuccessMessage("Routing complete!"); // Update the display setHighlightStartNode(m_controlsDock->highlightStartNode()); setHighlightEndNode(m_controlsDock->highlightEndNode()); setHighlightPath(m_controlsDock->highlightPath()); }