Пример #1
0
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));
}
Пример #2
0
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());
}