From dfdbe65c5b4e7d498e8a1432b90e3fbe7b308546 Mon Sep 17 00:00:00 2001 From: Denes Matetelki Date: Sun, 7 Sep 2014 17:26:04 +0200 Subject: [PATCH] Using dijkstra, buggy. --- .gitignore | 1 + lib/qtgraph/CMakeLists.txt | 4 +-- lib/qtgraph/edge.cpp | 7 +++- lib/qtgraph/edge.hpp | 4 +++ lib/qtgraph/graphwidget.cpp | 72 ++++++++++++++++++++++++++++++++++++- lib/qtgraph/graphwidget.hpp | 2 ++ lib/qtgraph/main.cpp | 25 ++++++++++--- lib/qtgraph/node.cpp | 11 ++++++ lib/qtgraph/node.hpp | 2 +- 9 files changed, 117 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index e5ad2c3..9c0d653 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ cmake_install.cmake # graph graph.kdev4 libstdcxx-profile.* +*.xml diff --git a/lib/qtgraph/CMakeLists.txt b/lib/qtgraph/CMakeLists.txt index 0b516a1..9ef4870 100644 --- a/lib/qtgraph/CMakeLists.txt +++ b/lib/qtgraph/CMakeLists.txt @@ -1,8 +1,6 @@ cmake_minimum_required (VERSION 2.6) project (PROJECT_QGRAPH) -set ( CMAKE_CXX_COMPILER "/usr/bin/g++-4.9.0") - set (CXX_FLAGS "-Wall -Wextra -pedantic -Wshadow " "-Wpointer-arith -Wcast-qual " "-ggdb " @@ -37,4 +35,4 @@ make clean && find -iname '*cmake*' -not -name CMakeLists.txt -exec rm -rf {} \\+ && rm Makefile && rm moc_* -) \ No newline at end of file +) diff --git a/lib/qtgraph/edge.cpp b/lib/qtgraph/edge.cpp index cb12fd8..dfecb99 100644 --- a/lib/qtgraph/edge.cpp +++ b/lib/qtgraph/edge.cpp @@ -11,6 +11,7 @@ static double TwoPi = 2.0 * Pi; Edge::Edge(Node* s, Node* d, Edge::ArrowStyle arrowStyle ) : m_arrowStyle(arrowStyle) , arrowSize(10) + , m_isRoute(false) { setAcceptedMouseButtons(0); source = s; @@ -73,7 +74,11 @@ void Edge::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) return; // Draw the line itself - painter->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + if (m_isRoute) + painter->setPen(QPen(Qt::red, 10, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + else + painter->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + painter->drawLine(line); // Draw the arrows diff --git a/lib/qtgraph/edge.hpp b/lib/qtgraph/edge.hpp index 2a5968a..c653b82 100644 --- a/lib/qtgraph/edge.hpp +++ b/lib/qtgraph/edge.hpp @@ -21,6 +21,9 @@ public: Node *sourceNode() const; Node *destNode() const; + bool isRoute() const { return m_isRoute; } + void setIsRoute(bool is_route = true) { m_isRoute = is_route; update(); } + void adjust(); enum { Type = UserType + 2 }; @@ -37,6 +40,7 @@ private: QPointF sourcePoint; QPointF destPoint; qreal arrowSize; + bool m_isRoute; }; #endif diff --git a/lib/qtgraph/graphwidget.cpp b/lib/qtgraph/graphwidget.cpp index 2763f1b..ce6d0d0 100644 --- a/lib/qtgraph/graphwidget.cpp +++ b/lib/qtgraph/graphwidget.cpp @@ -4,6 +4,7 @@ #include "node.hpp" #include +#include #include "floats.hpp" #include @@ -12,7 +13,7 @@ #include -#include +#include namespace std { template <> @@ -25,6 +26,15 @@ namespace std { return h1 ^ (h2 << 1); } }; + + class distanceOf2float2s : public std::function + { + public: + float operator()(float2 a, float2 b) + { + return dist(a, b); + } + }; } namespace { @@ -35,6 +45,8 @@ namespace { // return length(v1) < length(v2); // } + + float2 inline float2FromQPointF(const QPointF& p) { return float2(p.x(), p.y()); @@ -45,6 +57,40 @@ QPointF inline QPointFFromfloat2(const float2& f) return QPointF(f.x, f.y); } +inline float dist(const float2& v1, const float2& v2) +{ + return sqrt(pow((v2.x - v1.x),2) + pow((v2.y - v1.y),2)); +} + +QList calculateShortestRoute(const QGraphicsScene* scene, + const Graph* graph, + const Node* source, + const Node* destination) +{ + + const float2 s = float2FromQPointF(source->pos()); + const float2 d = float2FromQPointF(destination->pos()); + const std::vector shortestPath = dijkstra_shortest_path_to(*graph, s, d, std::distanceOf2float2s()); + + QList route; + const int lenghtOfRoute = shortestPath.size(); + if (lenghtOfRoute < 2) + return route; + + for (int i = 0; i < lenghtOfRoute; ++i) { + if (i+1 == lenghtOfRoute) + break; + + QGraphicsItem* source_item = scene->itemAt(QPointFFromfloat2(shortestPath[i])); + QGraphicsItem* destination_item = scene->itemAt(QPointFFromfloat2(shortestPath[i+1])); + Node* source_node = dynamic_cast(source_item); + Node* destination_node = dynamic_cast(destination_item); + Edge* e = source_node->edgeTo(destination_node); + route.append(e); + } + return route; +} + } // anonym namespace @@ -131,6 +177,30 @@ void GraphWidget::keyPressEvent(QKeyEvent *e) } break; } + case Qt::Key_Space: { + for (QList::iterator it = m_route.begin(); it != m_route.end(); ++it) + (*it)->setIsRoute(false); + + QList selectedItems = scene()->selectedItems(); + if (selectedItems.isEmpty()) + break; + + QGraphicsItem* selectedItem = selectedItems.first(); + Node* selectedNode = dynamic_cast(selectedItem); + + const QPoint global_p = QCursor::pos(); + const QPoint widget_p = mapFromGlobal(global_p); + const QPointF scene_p = mapToScene(widget_p); + + QGraphicsItem* item_under_mouse = scene()->itemAt(scene_p); + Node* nodeUnderMouse = dynamic_cast(item_under_mouse); + + if (nodeUnderMouse != 0 && nodeUnderMouse != selectedNode) { + m_route = calculateShortestRoute(scene(), m_graph, selectedNode, nodeUnderMouse); + for (QList::iterator it = m_route.begin(); it != m_route.end(); ++it) + (*it)->setIsRoute(true); + } + } default: QGraphicsView::keyPressEvent(e); } diff --git a/lib/qtgraph/graphwidget.hpp b/lib/qtgraph/graphwidget.hpp index debf1e5..b3c3f3d 100644 --- a/lib/qtgraph/graphwidget.hpp +++ b/lib/qtgraph/graphwidget.hpp @@ -6,6 +6,7 @@ class float2; template class Graph; class Node; +class Edge; class GraphWidget : public QGraphicsView { @@ -37,6 +38,7 @@ private: void removeEdge(Node* selectedNode, Node* nodeUnderMouse); Graph* m_graph; + QList m_route; }; #endif diff --git a/lib/qtgraph/main.cpp b/lib/qtgraph/main.cpp index df76d42..0339b75 100644 --- a/lib/qtgraph/main.cpp +++ b/lib/qtgraph/main.cpp @@ -2,8 +2,6 @@ #include #include -#include - #include #include @@ -52,14 +50,31 @@ float2 float2creator(const std::string& line) inline std::string float2serializer(const float2& f2) { return std::to_string_with_precision(f2.x, 3) + " " + std::to_string_with_precision(f2.y, 3); + } +// https://stackoverflow.com/questions/13878373/where-am-i-supposed-to-reimplement-qapplicationnotify-function +class SafeQApplication : public QApplication +{ +public: + SafeQApplication(int &argCounter, char ** argVector) : QApplication(argCounter, argVector) {} +private: + bool notify(QObject *receiver_, QEvent *event_) + { + try { + return QApplication::notify(receiver_, event_); + } catch (std::exception &ex) { + std::cerr << "std::exception was caught " << ex.what() << std::endl; + } + return false; + } +}; + + int main(int argc, char **argv) { - QApplication app(argc, argv); - qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); - + SafeQApplication app(argc, argv); const std::string xml_file = "graph_example.xml"; Graph g = readGraphFromXML(xml_file, float2creator); diff --git a/lib/qtgraph/node.cpp b/lib/qtgraph/node.cpp index b38ae4e..d20bcc3 100644 --- a/lib/qtgraph/node.cpp +++ b/lib/qtgraph/node.cpp @@ -35,6 +35,17 @@ QList Node::edges() const return edgeList; } +Edge* Node::edgeTo(const Node* n) const +{ + for (int i = 0; i < edgeList.size(); ++i) { + Edge* e = edgeList.at(i); + if (e->destNode() == n) + return e; + } + return 0; +} + + QRectF Node::boundingRect() const { qreal adjust = 2; diff --git a/lib/qtgraph/node.hpp b/lib/qtgraph/node.hpp index 0c4b7b1..390e43f 100644 --- a/lib/qtgraph/node.hpp +++ b/lib/qtgraph/node.hpp @@ -16,6 +16,7 @@ public: void addEdge(Edge *edge); void removeEdge(Edge* edge); QList edges() const; + Edge* edgeTo(const Node* n) const; enum { Type = UserType + 1 }; int type() const override { return Type; } @@ -31,7 +32,6 @@ protected: private: QList edgeList; - QPointF newPos; GraphWidget *m_graphWidget; };