Showing
7 changed files
with
204 additions
and
131 deletions
| ... | @@ -13,13 +13,13 @@ void NodeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * event) | ... | @@ -13,13 +13,13 @@ void NodeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * event) |
| 13 | { | 13 | { |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | -NodeItem::NodeItem(int x, int y) | 16 | +NodeItem::NodeItem(int x, int y, QString label) |
| 17 | { | 17 | { |
| 18 | this->x = x; | 18 | this->x = x; |
| 19 | this->y = y; | 19 | this->y = y; |
| 20 | - //this->color = QColor(Qt::green); //R, G, B | ||
| 21 | this->color = QColor(Qt::green); | 20 | this->color = QColor(Qt::green); |
| 22 | - setZValue((x+y)%2); | 21 | + this->label = label; |
| 22 | + setZValue(1); | ||
| 23 | 23 | ||
| 24 | setFlags(ItemIsSelectable | ItemIsMovable); | 24 | setFlags(ItemIsSelectable | ItemIsMovable); |
| 25 | setAcceptHoverEvents(true); | 25 | setAcceptHoverEvents(true); |
| ... | @@ -42,100 +42,23 @@ void NodeItem::paint(QPainter * painter, const QStyleOptionGraphicsItem * option | ... | @@ -42,100 +42,23 @@ void NodeItem::paint(QPainter * painter, const QStyleOptionGraphicsItem * option |
| 42 | { | 42 | { |
| 43 | Q_UNUSED(widget); | 43 | Q_UNUSED(widget); |
| 44 | 44 | ||
| 45 | - //QColor fillColor = (option->state & QStyle::State_Selected) ? color.dark(150) : color; | 45 | + //label |
| 46 | - //if (option->state & QStyle::State_MouseOver) | 46 | + QFont font("Gulim", 10); |
| 47 | - // fillColor = fillColor.light(125); | 47 | + font.setStyleStrategy(QFont::ForceOutline); |
| 48 | + painter->setFont(font); | ||
| 49 | + painter->save(); | ||
| 50 | + painter->scale(0.3, 0.3); | ||
| 51 | + painter->drawText(0, 0, label); | ||
| 52 | + painter->restore(); | ||
| 48 | 53 | ||
| 49 | - //const qreal& lod = option->levelOfDetailFromTransform(painter->worldTransform()); | ||
| 50 | - //if (lod < 0.2) { | ||
| 51 | - // if (lod < 0.125) { | ||
| 52 | - // painter->fillRect(QRectF(0, 0, 110, 70), fillColor); | ||
| 53 | - // return; | ||
| 54 | - // } | ||
| 55 | - | ||
| 56 | - // QBrush b = painter->brush(); | ||
| 57 | - // painter->setBrush(fillColor); | ||
| 58 | - // painter->drawRect(13, 13, 97, 57); | ||
| 59 | - // painter->setBrush(b); | ||
| 60 | - // return; | ||
| 61 | - //} | ||
| 62 | - | ||
| 63 | - //QPen oldPen = painter->pen(); | ||
| 64 | - //QPen pen = oldPen; | ||
| 65 | - //int width = 0; | ||
| 66 | - //if (option->state & QStyle::State_Selected) | ||
| 67 | - // width += 2; | ||
| 68 | - | ||
| 69 | - //pen.setWidth(width); | ||
| 70 | - //QBrush b = painter->brush(); | ||
| 71 | - //painter->setBrush(QBrush(fillColor.dark(option->state & QStyle::State_Sunken ? 120 : 100))); | ||
| 72 | - | ||
| 73 | - //painter->drawRect(QRect(14, 14, 79, 39)); | ||
| 74 | - //painter->setBrush(b); | ||
| 75 | - | ||
| 76 | - //if (lod >= 1) { | ||
| 77 | - // painter->setPen(QPen(Qt::gray, 1)); | ||
| 78 | - // painter->drawLine(15, 54, 94, 54); | ||
| 79 | - // painter->drawLine(94, 53, 94, 15); | ||
| 80 | - // painter->setPen(QPen(Qt::black, 0)); | ||
| 81 | - //} | ||
| 82 | 54 | ||
| 55 | + //Rectangle | ||
| 83 | QColor fillColor = (option->state & QStyle::State_Selected) ? color.dark(150) : color; | 56 | QColor fillColor = (option->state & QStyle::State_Selected) ? color.dark(150) : color; |
| 84 | if (option->state & QStyle::State_MouseOver) fillColor = fillColor.light(125); | 57 | if (option->state & QStyle::State_MouseOver) fillColor = fillColor.light(125); |
| 85 | - painter->setPen(QPen(Qt::black)); | 58 | + QPen pen = painter->pen(); |
| 59 | + pen.setWidth(0); | ||
| 60 | + pen.setColor(QColor(Qt::black)); | ||
| 61 | + painter->setPen(pen); | ||
| 86 | painter->setBrush(QBrush(fillColor)); | 62 | painter->setBrush(QBrush(fillColor)); |
| 87 | painter->drawRect(0, 0, NODE_SIZE, NODE_SIZE); | 63 | painter->drawRect(0, 0, NODE_SIZE, NODE_SIZE); |
| 88 | - //painter->fillRect(QRectF(0, 0, NODE_SIZE, NODE_SIZE), fillColor); | ||
| 89 | - //painter->drawRect(0, 0, NODE_SIZE, NODE_SIZE); | ||
| 90 | - | ||
| 91 | - // Draw text | ||
| 92 | - //if (lod >= 2) { | ||
| 93 | - // QFont font("Times", 10); | ||
| 94 | - // font.setStyleStrategy(QFont::ForceOutline); | ||
| 95 | - // painter->setFont(font); | ||
| 96 | - // painter->save(); | ||
| 97 | - // painter->scale(0.1, 0.1); | ||
| 98 | - // painter->drawText(170, 180, QString("Model: VSC-2000 (Very Small Chip) at %1x%2").arg(x).arg(y)); | ||
| 99 | - // painter->drawText(170, 200, QString("Serial number: DLWR-WEER-123L-ZZ33-SDSJ")); | ||
| 100 | - // painter->drawText(170, 220, QString("Manufacturer: Chip Manufacturer")); | ||
| 101 | - // painter->restore(); | ||
| 102 | - //} | ||
| 103 | - | ||
| 104 | - // Draw lines | ||
| 105 | - //QVarLengthArray<QLineF, 36> lines; | ||
| 106 | - //if (lod >= 0.5) { | ||
| 107 | - // for (int i = 0; i <= 10; i += (lod > 0.5 ? 1 : 2)) { | ||
| 108 | - // lines.append(QLineF(18 + 7 * i, 13, 18 + 7 * i, 5)); | ||
| 109 | - // lines.append(QLineF(18 + 7 * i, 54, 18 + 7 * i, 62)); | ||
| 110 | - // } | ||
| 111 | - // for (int i = 0; i <= 6; i += (lod > 0.5 ? 1 : 2)) { | ||
| 112 | - // lines.append(QLineF(5, 18 + i * 5, 13, 18 + i * 5)); | ||
| 113 | - // lines.append(QLineF(94, 18 + i * 5, 102, 18 + i * 5)); | ||
| 114 | - // } | ||
| 115 | - //} | ||
| 116 | - //if (lod >= 0.4) { | ||
| 117 | - // const QLineF lineData[] = { | ||
| 118 | - // QLineF(25, 35, 35, 35), | ||
| 119 | - // QLineF(35, 30, 35, 40), | ||
| 120 | - // QLineF(35, 30, 45, 35), | ||
| 121 | - // QLineF(35, 40, 45, 35), | ||
| 122 | - // QLineF(45, 30, 45, 40), | ||
| 123 | - // QLineF(45, 35, 55, 35) | ||
| 124 | - // }; | ||
| 125 | - // lines.append(lineData, 6); | ||
| 126 | - //} | ||
| 127 | - //painter->drawLines(lines.data(), lines.size()); | ||
| 128 | - | ||
| 129 | - // Draw red ink | ||
| 130 | - //if (stuff.size() > 1) { | ||
| 131 | - // QPen p = painter->pen(); | ||
| 132 | - // painter->setPen(QPen(Qt::red, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); | ||
| 133 | - // painter->setBrush(Qt::NoBrush); | ||
| 134 | - // QPainterPath path; | ||
| 135 | - // path.moveTo(stuff.first()); | ||
| 136 | - // for (int i = 1; i < stuff.size(); ++i) | ||
| 137 | - // path.lineTo(stuff.at(i)); | ||
| 138 | - // painter->drawPath(path); | ||
| 139 | - // painter->setPen(p); | ||
| 140 | - //} | ||
| 141 | } | 64 | } | ... | ... |
| ... | @@ -14,6 +14,7 @@ private: | ... | @@ -14,6 +14,7 @@ private: |
| 14 | int x; | 14 | int x; |
| 15 | int y; | 15 | int y; |
| 16 | QColor color; | 16 | QColor color; |
| 17 | + QString label; | ||
| 17 | 18 | ||
| 18 | protected: | 19 | protected: |
| 19 | void mousePressEvent(QGraphicsSceneMouseEvent *event) override; | 20 | void mousePressEvent(QGraphicsSceneMouseEvent *event) override; |
| ... | @@ -21,7 +22,7 @@ protected: | ... | @@ -21,7 +22,7 @@ protected: |
| 21 | void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; | 22 | void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; |
| 22 | 23 | ||
| 23 | public: | 24 | public: |
| 24 | - NodeItem(int x, int y); | 25 | + NodeItem(int x, int y, QString label); |
| 25 | 26 | ||
| 26 | QRectF boundingRect() const override; | 27 | QRectF boundingRect() const override; |
| 27 | QPainterPath shape() const override; | 28 | QPainterPath shape() const override; | ... | ... |
| ... | @@ -145,6 +145,7 @@ | ... | @@ -145,6 +145,7 @@ |
| 145 | </Link> | 145 | </Link> |
| 146 | </ItemDefinitionGroup> | 146 | </ItemDefinitionGroup> |
| 147 | <ItemGroup> | 147 | <ItemGroup> |
| 148 | + <ClCompile Include="EdgeItem.cpp" /> | ||
| 148 | <ClCompile Include="GeneratedFiles\Debug\moc_GraphicsView.cpp"> | 149 | <ClCompile Include="GeneratedFiles\Debug\moc_GraphicsView.cpp"> |
| 149 | <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> | 150 | <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> |
| 150 | <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> | 151 | <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> |
| ... | @@ -217,6 +218,7 @@ | ... | @@ -217,6 +218,7 @@ |
| 217 | </CustomBuild> | 218 | </CustomBuild> |
| 218 | </ItemGroup> | 219 | </ItemGroup> |
| 219 | <ItemGroup> | 220 | <ItemGroup> |
| 221 | + <ClInclude Include="EdgeItem.h" /> | ||
| 220 | <ClInclude Include="GeneratedFiles\ui_PaperGraphWidget.h" /> | 222 | <ClInclude Include="GeneratedFiles\ui_PaperGraphWidget.h" /> |
| 221 | <CustomBuild Include="GraphicsView.h"> | 223 | <CustomBuild Include="GraphicsView.h"> |
| 222 | <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs> | 224 | <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs> | ... | ... |
| ... | @@ -62,6 +62,9 @@ | ... | @@ -62,6 +62,9 @@ |
| 62 | <ClCompile Include="GeneratedFiles\Release\moc_GraphicsView.cpp"> | 62 | <ClCompile Include="GeneratedFiles\Release\moc_GraphicsView.cpp"> |
| 63 | <Filter>Generated Files\Release</Filter> | 63 | <Filter>Generated Files\Release</Filter> |
| 64 | </ClCompile> | 64 | </ClCompile> |
| 65 | + <ClCompile Include="EdgeItem.cpp"> | ||
| 66 | + <Filter>Source Files</Filter> | ||
| 67 | + </ClCompile> | ||
| 65 | </ItemGroup> | 68 | </ItemGroup> |
| 66 | <ItemGroup> | 69 | <ItemGroup> |
| 67 | <CustomBuild Include="PaperGraphWidget.h"> | 70 | <CustomBuild Include="PaperGraphWidget.h"> |
| ... | @@ -84,5 +87,8 @@ | ... | @@ -84,5 +87,8 @@ |
| 84 | <ClInclude Include="NodeItem.h"> | 87 | <ClInclude Include="NodeItem.h"> |
| 85 | <Filter>Header Files</Filter> | 88 | <Filter>Header Files</Filter> |
| 86 | </ClInclude> | 89 | </ClInclude> |
| 90 | + <ClInclude Include="EdgeItem.h"> | ||
| 91 | + <Filter>Header Files</Filter> | ||
| 92 | + </ClInclude> | ||
| 87 | </ItemGroup> | 93 | </ItemGroup> |
| 88 | </Project> | 94 | </Project> |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | #include "PaperGraphWidget.h" | 1 | #include "PaperGraphWidget.h" |
| 2 | #include "NodeItem.h" | 2 | #include "NodeItem.h" |
| 3 | +#include "EdgeItem.h" | ||
| 3 | #include "GraphicsView.h" | 4 | #include "GraphicsView.h" |
| 4 | 5 | ||
| 6 | +#include <string> | ||
| 7 | + | ||
| 5 | PaperGraphWidget::PaperGraphWidget(QWidget *parent) | 8 | PaperGraphWidget::PaperGraphWidget(QWidget *parent) |
| 6 | : QWidget(parent) | 9 | : QWidget(parent) |
| 7 | { | 10 | { |
| ... | @@ -20,6 +23,52 @@ PaperGraphWidget::PaperGraphWidget(QWidget *parent) | ... | @@ -20,6 +23,52 @@ PaperGraphWidget::PaperGraphWidget(QWidget *parent) |
| 20 | void PaperGraphWidget::print_graph(const Graph & graph) | 23 | void PaperGraphWidget::print_graph(const Graph & graph) |
| 21 | { | 24 | { |
| 22 | //print graph | 25 | //print graph |
| 26 | + typedef square_topology<> Topology; | ||
| 27 | + typedef typename Topology::point_type Point; | ||
| 28 | + const int rect_sz = 4; | ||
| 29 | + auto position = get(vertex_position, graph); | ||
| 30 | + auto label = get(vertex_name, graph); | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + | ||
| 34 | + //print edges | ||
| 35 | + typename graph_traits<Graph>::edge_iterator ei, ei_end; | ||
| 36 | + typedef boost::graph_traits<Graph>::vertex_descriptor VertexDescriptor; | ||
| 37 | + VertexDescriptor u, v; | ||
| 38 | + for (boost::tie(ei, ei_end)=edges(graph); ei!=ei_end; ++ei) { | ||
| 39 | + u = source(*ei, graph); | ||
| 40 | + v = target(*ei, graph); | ||
| 41 | + | ||
| 42 | + Point p1 = position[u]; | ||
| 43 | + Point p2 = position[v]; | ||
| 44 | + | ||
| 45 | + /*line = scene->addLine( | ||
| 46 | + p1[0], p1[1], | ||
| 47 | + p2[0], p2[1], | ||
| 48 | + QPen(Qt::black) | ||
| 49 | + );*/ | ||
| 50 | + //QGraphicsItem *edge = | ||
| 51 | + // new EdgeItem(p1[0], p1[1], p2[0], p2[1]); | ||
| 52 | + //edge->setPos(QPointF(p1[0], p1[1])); | ||
| 53 | + //scene->addItem(edge); | ||
| 54 | + | ||
| 55 | + scene->addLine(p1[0], p1[1], p2[0], p2[1], QPen(Qt::black, 0)); | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + //print nodes | ||
| 59 | + typename graph_traits<Graph>::vertex_iterator vi, vi_end; | ||
| 60 | + for (boost::tie(vi, vi_end)=vertices(graph); vi!=vi_end; ++vi) { | ||
| 61 | + //Point p = position[*vi]; | ||
| 62 | + //rectangle = scene->addRect( | ||
| 63 | + // p[0], p[1], rect_sz, rect_sz, | ||
| 64 | + // QPen(Qt::black), | ||
| 65 | + // QBrush(Qt::green)); | ||
| 66 | + Point p = position[*vi]; | ||
| 67 | + std::string name = label[*vi]; | ||
| 68 | + QGraphicsItem *node = new NodeItem(p[0], p[1], QString(name.c_str())); | ||
| 69 | + node->setPos(QPointF(p[0], p[1])); | ||
| 70 | + scene->addItem(node); | ||
| 71 | + } | ||
| 23 | } | 72 | } |
| 24 | 73 | ||
| 25 | void PaperGraphWidget::initscene() | 74 | void PaperGraphWidget::initscene() | ... | ... |
| ... | @@ -5,8 +5,8 @@ | ... | @@ -5,8 +5,8 @@ |
| 5 | #include <QGraphicsScene> | 5 | #include <QGraphicsScene> |
| 6 | 6 | ||
| 7 | #include <boost/graph/adjacency_list.hpp> | 7 | #include <boost/graph/adjacency_list.hpp> |
| 8 | -#include <boost/graph/kamada_kawai_spring_layout.hpp> | 8 | +#include <boost/graph/topology.hpp> |
| 9 | -#include <boost/graph/random_layout.hpp> | 9 | +#include <boost/graph/graph_traits.hpp> |
| 10 | 10 | ||
| 11 | #include "ui_PaperGraphWidget.h" | 11 | #include "ui_PaperGraphWidget.h" |
| 12 | 12 | ||
| ... | @@ -33,7 +33,6 @@ typedef adjacency_list< | ... | @@ -33,7 +33,6 @@ typedef adjacency_list< |
| 33 | listS, //VertexList | 33 | listS, //VertexList |
| 34 | undirectedS, | 34 | undirectedS, |
| 35 | //vertex properties | 35 | //vertex properties |
| 36 | - //VertexProperties, | ||
| 37 | VertexProperties, | 36 | VertexProperties, |
| 38 | //edge properties | 37 | //edge properties |
| 39 | boost::property<edge_weight_t, double> | 38 | boost::property<edge_weight_t, double> | ... | ... |
| ... | @@ -10,14 +10,29 @@ | ... | @@ -10,14 +10,29 @@ |
| 10 | #include <map> | 10 | #include <map> |
| 11 | #include <vector> | 11 | #include <vector> |
| 12 | 12 | ||
| 13 | +#include <boost/graph/fruchterman_reingold.hpp> | ||
| 14 | +//#include <boost/graph/kamada_kawai_spring_layout.hpp> | ||
| 15 | +#include <boost/graph/random_layout.hpp> | ||
| 16 | +#include <boost/graph/circle_layout.hpp> | ||
| 17 | +#include <boost/graph/dijkstra_shortest_paths.hpp> | ||
| 13 | #include <boost/algorithm/string.hpp> //boost::split | 18 | #include <boost/algorithm/string.hpp> //boost::split |
| 14 | -//#include <boost/bind.hpp> | ||
| 15 | #include <boost/bimap.hpp> | 19 | #include <boost/bimap.hpp> |
| 16 | 20 | ||
| 17 | using namespace std; | 21 | using namespace std; |
| 18 | 22 | ||
| 19 | - | 23 | +/** |
| 20 | -const string PAPER_FILENAME = "dblp-paper.txt"; | 24 | + * Constants |
| 25 | + */ | ||
| 26 | +const char* PAPER_FILENAME = "dblp-paper.txt"; | ||
| 27 | +enum GRAPH_LAYOUT { | ||
| 28 | + RANDOM_LAYOUT, | ||
| 29 | + CIRCLE_LAYOUT, | ||
| 30 | + //KAMADA_KAWAI_LAYOUT, | ||
| 31 | + FRUCHTERMAN_REINGOLD_LAYOUT //slow | ||
| 32 | +}; | ||
| 33 | +const int LAYOUT_MODE = GRAPH_LAYOUT::RANDOM_LAYOUT; | ||
| 34 | +const int SCREEN_SIZE = 500; | ||
| 35 | +const int NODE_LIMIT = 100; | ||
| 21 | 36 | ||
| 22 | Graph read_graph(ifstream& in) { | 37 | Graph read_graph(ifstream& in) { |
| 23 | /** | 38 | /** |
| ... | @@ -31,82 +46,160 @@ Graph read_graph(ifstream& in) { | ... | @@ -31,82 +46,160 @@ Graph read_graph(ifstream& in) { |
| 31 | vector<std::string> authors; | 46 | vector<std::string> authors; |
| 32 | vector<pair<string, string>> edges; | 47 | vector<pair<string, string>> edges; |
| 33 | 48 | ||
| 49 | + //String <--> int 양방향 변환을 위해 bidirectional map 상숑 | ||
| 34 | typedef boost::bimap<string, int> bm_type; | 50 | typedef boost::bimap<string, int> bm_type; |
| 35 | bm_type node_ids; | 51 | bm_type node_ids; |
| 36 | - vector<simple_edge> edges_indexes; | 52 | + vector<simple_edge> edges_indexes; //int로 변환된 edge |
| 53 | + | ||
| 37 | int node_cnt = 0; | 54 | int node_cnt = 0; |
| 38 | - qDebug() << "* graph reading start" << endl; | 55 | + qDebug() << "* graph reading start"; |
| 56 | + | ||
| 57 | + //한 줄씩 읽어서 Parse | ||
| 39 | while (std::getline(in, line) && !line.empty()) { | 58 | while (std::getline(in, line) && !line.empty()) { |
| 59 | + //boost::split 이용해 문자열 분리 | ||
| 60 | + //tokens[0]: Paper-key. ex) conf/iastedCSN/KeimS06 | ||
| 61 | + //tokens[1]: Authors. ex) Werner Keim&&Arpad L. Scholtz | ||
| 62 | + //tokens[2]: Published year. | ||
| 40 | boost::split(tokens, line, boost::is_any_of("||"), boost::token_compress_on); | 63 | boost::split(tokens, line, boost::is_any_of("||"), boost::token_compress_on); |
| 41 | boost::split(authors, tokens[1], boost::is_any_of("&&"), boost::token_compress_on); | 64 | boost::split(authors, tokens[1], boost::is_any_of("&&"), boost::token_compress_on); |
| 42 | 65 | ||
| 43 | const string& paper_key = tokens[0]; | 66 | const string& paper_key = tokens[0]; |
| 44 | if (node_ids.left.find(paper_key) == node_ids.left.end()) { | 67 | if (node_ids.left.find(paper_key) == node_ids.left.end()) { |
| 45 | - //node_ids[paper_key] = node_cnt++; | ||
| 46 | node_ids.insert(bm_type::value_type(paper_key, node_cnt++)); | 68 | node_ids.insert(bm_type::value_type(paper_key, node_cnt++)); |
| 47 | - //qDebug() << paper_key.c_str() << " "; | ||
| 48 | } | 69 | } |
| 49 | 70 | ||
| 50 | for (auto author : authors) { | 71 | for (auto author : authors) { |
| 51 | edges.push_back(pair<string, string>(paper_key, author)); | 72 | edges.push_back(pair<string, string>(paper_key, author)); |
| 52 | if (node_ids.left.find(author) == node_ids.left.end()) { | 73 | if (node_ids.left.find(author) == node_ids.left.end()) { |
| 53 | - //node_ids[author] = node_cnt++; | ||
| 54 | node_ids.insert(bm_type::value_type(author, node_cnt++)); | 74 | node_ids.insert(bm_type::value_type(author, node_cnt++)); |
| 55 | - //qDebug() << author.c_str() << " "; | ||
| 56 | - | ||
| 57 | } | 75 | } |
| 58 | } | 76 | } |
| 59 | 77 | ||
| 60 | - | ||
| 61 | //debug | 78 | //debug |
| 62 | - if (node_cnt > 100) break; | 79 | + if (node_cnt > NODE_LIMIT) break; |
| 63 | } | 80 | } |
| 64 | - qDebug() << "* graph reading complete" << endl; | 81 | + qDebug() << "* graph reading complete"; |
| 65 | - | 82 | + qDebug() << "* # of nodes: " << node_cnt; |
| 66 | - //std::sort(node_names.begin(), node_names.end()); | 83 | + qDebug() << "* # of edges: " << edges.size(); |
| 67 | 84 | ||
| 68 | - //Make graph | 85 | + //edge conversion |
| 69 | - //Graph --> defined in "PaperGraphWidget.h" | 86 | + //<string, string> to <int, int> |
| 70 | - | 87 | + //using boost::bimap (bidirectional map) |
| 71 | for (auto edge : edges) { | 88 | for (auto edge : edges) { |
| 72 | edges_indexes.push_back({ | 89 | edges_indexes.push_back({ |
| 73 | node_ids.left.find(edge.first)->get_right(), | 90 | node_ids.left.find(edge.first)->get_right(), |
| 74 | node_ids.left.find(edge.second)->get_right() | 91 | node_ids.left.find(edge.second)->get_right() |
| 75 | }); | 92 | }); |
| 76 | } | 93 | } |
| 94 | + //Graph --> defined in "PaperGraphWidget.h" | ||
| 77 | Graph graph(edges_indexes.begin(), edges_indexes.end(), node_ids.size()); | 95 | Graph graph(edges_indexes.begin(), edges_indexes.end(), node_ids.size()); |
| 78 | 96 | ||
| 79 | - //print map | ||
| 80 | - //for (auto it=node_ids.left.begin(), itend=node_ids.left.end(); | ||
| 81 | - // it!=itend; ++it) { | ||
| 82 | - // qDebug() << it->first.c_str() << " " << it->second << endl; | ||
| 83 | - //} | ||
| 84 | - | ||
| 85 | //set index property | 97 | //set index property |
| 98 | + qDebug() << "* set vertex property start"; | ||
| 86 | typedef typename graph_traits<Graph>::edge_iterator edge_iterator; | 99 | typedef typename graph_traits<Graph>::edge_iterator edge_iterator; |
| 87 | typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator; | 100 | typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator; |
| 88 | vertex_iterator vi, vi_end; | 101 | vertex_iterator vi, vi_end; |
| 89 | int i = 0; | 102 | int i = 0; |
| 90 | for (boost::tie(vi, vi_end)=vertices(graph); vi!=vi_end; ++vi) { | 103 | for (boost::tie(vi, vi_end)=vertices(graph); vi!=vi_end; ++vi) { |
| 104 | + //Vertex Property 설정 | ||
| 105 | + //index: 0 ~ ... | ||
| 106 | + //name : map의 value(i) 기준으로 찾은 Key | ||
| 107 | + // map --> map<string, int> (boost bidirectional map) | ||
| 91 | boost::put(vertex_index, graph, *vi, i); | 108 | boost::put(vertex_index, graph, *vi, i); |
| 92 | boost::put(vertex_name, graph, *vi, | 109 | boost::put(vertex_name, graph, *vi, |
| 93 | node_ids.right.find(i)->get_left()); | 110 | node_ids.right.find(i)->get_left()); |
| 94 | - //VertexProperties prop = VertexProperties(i, | ||
| 95 | - // boost::property<vertex_name_t, std::string, | ||
| 96 | - // boost::property<vertex_position_t, point>>()); | ||
| 97 | 111 | ||
| 98 | ++i; | 112 | ++i; |
| 99 | } | 113 | } |
| 114 | + qDebug() << "* set vertex property end"; | ||
| 100 | 115 | ||
| 101 | 116 | ||
| 102 | - //for (auto edge : edges) { | 117 | + //모든 edge weight 1로 만들기 |
| 103 | - // //add edge | 118 | + edge_iterator ei, ei_end; |
| 104 | - // //VertexProperties prop = VertexProperties() | 119 | + for (boost::tie(ei, ei_end)=boost::edges(graph); ei!=ei_end; ++ei) { |
| 105 | - // //add_edge(node_ids[edge.first], node_ids[edge.second],); | 120 | + boost::put(edge_weight, graph, *ei, 1); |
| 106 | - //} | 121 | + } |
| 107 | 122 | ||
| 108 | - //make graph layout | ||
| 109 | 123 | ||
| 124 | + //path finding between two vertices | ||
| 125 | + //using dijkstra algorithm | ||
| 126 | + //ex) "Werner Keim" ---> "Arpad L. Scholtz" (in dataset 2nd line) | ||
| 127 | + qDebug() << "* path finding start"; | ||
| 128 | + typedef graph_traits<Graph>::vertex_descriptor vertex_descriptor; | ||
| 129 | + std::vector<vertex_descriptor> parent(num_vertices(graph)); | ||
| 130 | + std::vector<int> distance(num_vertices(graph)); | ||
| 131 | + int start_idx = node_ids.left.find("Werner Keim")->get_right(); | ||
| 132 | + vertex_descriptor start_v = vertex(start_idx, graph); | ||
| 133 | + | ||
| 134 | + dijkstra_shortest_paths( | ||
| 135 | + graph, | ||
| 136 | + start_v, | ||
| 137 | + predecessor_map( | ||
| 138 | + boost::make_iterator_property_map(parent.begin(), get(boost::vertex_index, graph)) | ||
| 139 | + ).distance_map(boost::make_iterator_property_map(distance.begin(), get(boost::vertex_index, graph))) | ||
| 140 | + ); | ||
| 141 | + qDebug() << "* path finding end"; | ||
| 142 | + | ||
| 143 | + int aaaa = 3; | ||
| 144 | + | ||
| 145 | + | ||
| 146 | + //graph layout calculation | ||
| 147 | + //using boost::random_graph_layout and boost::kamada_kawai_spring_layout | ||
| 148 | + //vertex마다 계산된 좌표를 property에 적용 | ||
| 149 | + //예제 코드: http://www.boost.org/doc/libs/1_63_0/libs/graph/test/layout_test.cpp | ||
| 150 | + //(-> 콘솔 기반) | ||
| 151 | + qDebug() << "* make graph layout start"; | ||
| 152 | + typedef square_topology<> Topology; | ||
| 153 | + minstd_rand gen; | ||
| 154 | + Topology topology(gen, (double)SCREEN_SIZE); | ||
| 155 | + Topology::point_type origin; | ||
| 156 | + origin[0] = origin[1] = (double)SCREEN_SIZE; | ||
| 157 | + Topology::point_difference_type extent; | ||
| 158 | + extent[0] = extent[1] = (double)SCREEN_SIZE; | ||
| 159 | + rectangle_topology<> rect_top(gen, | ||
| 160 | + -SCREEN_SIZE/2, -SCREEN_SIZE/2, | ||
| 161 | + SCREEN_SIZE/2, SCREEN_SIZE/2); | ||
| 162 | + std::vector<Topology::point_difference_type> displacements(num_vertices(graph)); | ||
| 163 | + | ||
| 164 | + switch (LAYOUT_MODE) { | ||
| 165 | + case GRAPH_LAYOUT::RANDOM_LAYOUT: | ||
| 166 | + random_graph_layout(graph, get(vertex_position, graph), rect_top); | ||
| 167 | + break; | ||
| 168 | + | ||
| 169 | + case GRAPH_LAYOUT::CIRCLE_LAYOUT: | ||
| 170 | + circle_graph_layout(graph, get(vertex_position, graph), SCREEN_SIZE/2); | ||
| 171 | + break; | ||
| 172 | + | ||
| 173 | + //case GRAPH_LAYOUT::KAMADA_KAWAI_LAYOUT: | ||
| 174 | + // kamada_kawai_spring_layout(graph, | ||
| 175 | + // get(vertex_position, graph), | ||
| 176 | + // get(edge_weight, graph), | ||
| 177 | + // topology, | ||
| 178 | + // side_length((double)SCREEN_SIZE) | ||
| 179 | + // ); | ||
| 180 | + // break; | ||
| 181 | + | ||
| 182 | + case GRAPH_LAYOUT::FRUCHTERMAN_REINGOLD_LAYOUT: | ||
| 183 | + //fruchterman_reingold_force_directed_layout(graph, | ||
| 184 | + // get(vertex_position, graph), | ||
| 185 | + // topology, | ||
| 186 | + // square_distance_attractive_force(), | ||
| 187 | + // square_distance_repulsive_force(), | ||
| 188 | + // all_force_pairs(), | ||
| 189 | + // linear_cooling<double>(SCREEN_SIZE/2), | ||
| 190 | + // make_iterator_property_map(displacements.begin(), | ||
| 191 | + // get(vertex_index, graph), | ||
| 192 | + // Topology::point_difference_type()) | ||
| 193 | + //); | ||
| 194 | + fruchterman_reingold_force_directed_layout(graph, | ||
| 195 | + get(vertex_position, graph), | ||
| 196 | + topology, | ||
| 197 | + attractive_force(square_distance_attractive_force()) | ||
| 198 | + .cooling(linear_cooling<double>(50)) | ||
| 199 | + ); | ||
| 200 | + break; | ||
| 201 | + } | ||
| 202 | + qDebug() << "* make graph layout end"; | ||
| 110 | 203 | ||
| 111 | return graph; | 204 | return graph; |
| 112 | } | 205 | } |
| ... | @@ -114,7 +207,7 @@ Graph read_graph(ifstream& in) { | ... | @@ -114,7 +207,7 @@ Graph read_graph(ifstream& in) { |
| 114 | int main(int argc, char *argv[]) | 207 | int main(int argc, char *argv[]) |
| 115 | { | 208 | { |
| 116 | QApplication app(argc, argv); | 209 | QApplication app(argc, argv); |
| 117 | - app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); | 210 | + //app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); |
| 118 | 211 | ||
| 119 | PaperGraphWidget w; | 212 | PaperGraphWidget w; |
| 120 | 213 | ... | ... |
-
Please register or login to post a comment