Showing
14 changed files
with
873 additions
and
278 deletions
.gitignore
0 → 100644
1 | +## Ignore Visual Studio temporary files, build results, and | ||
2 | +## files generated by popular Visual Studio add-ons. | ||
3 | +## | ||
4 | +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore | ||
5 | + | ||
6 | +# User-specific files | ||
7 | +*.suo | ||
8 | +*.user | ||
9 | +*.userosscache | ||
10 | +*.sln.docstates | ||
11 | + | ||
12 | +# User-specific files (MonoDevelop/Xamarin Studio) | ||
13 | +*.userprefs | ||
14 | + | ||
15 | +# Build results | ||
16 | +[Dd]ebug/ | ||
17 | +[Dd]ebugPublic/ | ||
18 | +[Rr]elease/ | ||
19 | +[Rr]eleases/ | ||
20 | +x64/ | ||
21 | +x86/ | ||
22 | +bld/ | ||
23 | +[Bb]in/ | ||
24 | +[Oo]bj/ | ||
25 | +[Ll]og/ | ||
26 | + | ||
27 | +# Visual Studio 2015 cache/options directory | ||
28 | +.vs/ | ||
29 | +# Uncomment if you have tasks that create the project's static files in wwwroot | ||
30 | +#wwwroot/ | ||
31 | + | ||
32 | +# MSTest test Results | ||
33 | +[Tt]est[Rr]esult*/ | ||
34 | +[Bb]uild[Ll]og.* | ||
35 | + | ||
36 | +# NUNIT | ||
37 | +*.VisualState.xml | ||
38 | +TestResult.xml | ||
39 | + | ||
40 | +# Build Results of an ATL Project | ||
41 | +[Dd]ebugPS/ | ||
42 | +[Rr]eleasePS/ | ||
43 | +dlldata.c | ||
44 | + | ||
45 | +# .NET Core | ||
46 | +project.lock.json | ||
47 | +project.fragment.lock.json | ||
48 | +artifacts/ | ||
49 | +**/Properties/launchSettings.json | ||
50 | + | ||
51 | +*_i.c | ||
52 | +*_p.c | ||
53 | +*_i.h | ||
54 | +*.ilk | ||
55 | +*.meta | ||
56 | +*.obj | ||
57 | +*.pch | ||
58 | +*.pdb | ||
59 | +*.pgc | ||
60 | +*.pgd | ||
61 | +*.rsp | ||
62 | +*.sbr | ||
63 | +*.tlb | ||
64 | +*.tli | ||
65 | +*.tlh | ||
66 | +*.tmp | ||
67 | +*.tmp_proj | ||
68 | +*.log | ||
69 | +*.vspscc | ||
70 | +*.vssscc | ||
71 | +.builds | ||
72 | +*.pidb | ||
73 | +*.svclog | ||
74 | +*.scc | ||
75 | + | ||
76 | +# Chutzpah Test files | ||
77 | +_Chutzpah* | ||
78 | + | ||
79 | +# Visual C++ cache files | ||
80 | +ipch/ | ||
81 | +*.aps | ||
82 | +*.ncb | ||
83 | +*.opendb | ||
84 | +*.opensdf | ||
85 | +*.sdf | ||
86 | +*.cachefile | ||
87 | +*.VC.db | ||
88 | +*.VC.VC.opendb | ||
89 | + | ||
90 | +# Visual Studio profiler | ||
91 | +*.psess | ||
92 | +*.vsp | ||
93 | +*.vspx | ||
94 | +*.sap | ||
95 | + | ||
96 | +# TFS 2012 Local Workspace | ||
97 | +$tf/ | ||
98 | + | ||
99 | +# Guidance Automation Toolkit | ||
100 | +*.gpState | ||
101 | + | ||
102 | +# ReSharper is a .NET coding add-in | ||
103 | +_ReSharper*/ | ||
104 | +*.[Rr]e[Ss]harper | ||
105 | +*.DotSettings.user | ||
106 | + | ||
107 | +# JustCode is a .NET coding add-in | ||
108 | +.JustCode | ||
109 | + | ||
110 | +# TeamCity is a build add-in | ||
111 | +_TeamCity* | ||
112 | + | ||
113 | +# DotCover is a Code Coverage Tool | ||
114 | +*.dotCover | ||
115 | + | ||
116 | +# Visual Studio code coverage results | ||
117 | +*.coverage | ||
118 | +*.coveragexml | ||
119 | + | ||
120 | +# NCrunch | ||
121 | +_NCrunch_* | ||
122 | +.*crunch*.local.xml | ||
123 | +nCrunchTemp_* | ||
124 | + | ||
125 | +# MightyMoose | ||
126 | +*.mm.* | ||
127 | +AutoTest.Net/ | ||
128 | + | ||
129 | +# Web workbench (sass) | ||
130 | +.sass-cache/ | ||
131 | + | ||
132 | +# Installshield output folder | ||
133 | +[Ee]xpress/ | ||
134 | + | ||
135 | +# DocProject is a documentation generator add-in | ||
136 | +DocProject/buildhelp/ | ||
137 | +DocProject/Help/*.HxT | ||
138 | +DocProject/Help/*.HxC | ||
139 | +DocProject/Help/*.hhc | ||
140 | +DocProject/Help/*.hhk | ||
141 | +DocProject/Help/*.hhp | ||
142 | +DocProject/Help/Html2 | ||
143 | +DocProject/Help/html | ||
144 | + | ||
145 | +# Click-Once directory | ||
146 | +publish/ | ||
147 | + | ||
148 | +# Publish Web Output | ||
149 | +*.[Pp]ublish.xml | ||
150 | +*.azurePubxml | ||
151 | +# TODO: Comment the next line if you want to checkin your web deploy settings | ||
152 | +# but database connection strings (with potential passwords) will be unencrypted | ||
153 | +*.pubxml | ||
154 | +*.publishproj | ||
155 | + | ||
156 | +# Microsoft Azure Web App publish settings. Comment the next line if you want to | ||
157 | +# checkin your Azure Web App publish settings, but sensitive information contained | ||
158 | +# in these scripts will be unencrypted | ||
159 | +PublishScripts/ | ||
160 | + | ||
161 | +# NuGet Packages | ||
162 | +*.nupkg | ||
163 | +# The packages folder can be ignored because of Package Restore | ||
164 | +**/packages/* | ||
165 | +# except build/, which is used as an MSBuild target. | ||
166 | +!**/packages/build/ | ||
167 | +# Uncomment if necessary however generally it will be regenerated when needed | ||
168 | +#!**/packages/repositories.config | ||
169 | +# NuGet v3's project.json files produces more ignorable files | ||
170 | +*.nuget.props | ||
171 | +*.nuget.targets | ||
172 | + | ||
173 | +# Microsoft Azure Build Output | ||
174 | +csx/ | ||
175 | +*.build.csdef | ||
176 | + | ||
177 | +# Microsoft Azure Emulator | ||
178 | +ecf/ | ||
179 | +rcf/ | ||
180 | + | ||
181 | +# Windows Store app package directories and files | ||
182 | +AppPackages/ | ||
183 | +BundleArtifacts/ | ||
184 | +Package.StoreAssociation.xml | ||
185 | +_pkginfo.txt | ||
186 | + | ||
187 | +# Visual Studio cache files | ||
188 | +# files ending in .cache can be ignored | ||
189 | +*.[Cc]ache | ||
190 | +# but keep track of directories ending in .cache | ||
191 | +!*.[Cc]ache/ | ||
192 | + | ||
193 | +# Others | ||
194 | +ClientBin/ | ||
195 | +~$* | ||
196 | +*~ | ||
197 | +*.dbmdl | ||
198 | +*.dbproj.schemaview | ||
199 | +*.jfm | ||
200 | +*.pfx | ||
201 | +*.publishsettings | ||
202 | +orleans.codegen.cs | ||
203 | + | ||
204 | +# Since there are multiple workflows, uncomment next line to ignore bower_components | ||
205 | +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) | ||
206 | +#bower_components/ | ||
207 | + | ||
208 | +# RIA/Silverlight projects | ||
209 | +Generated_Code/ | ||
210 | + | ||
211 | +# Backup & report files from converting an old project file | ||
212 | +# to a newer Visual Studio version. Backup files are not needed, | ||
213 | +# because we have git ;-) | ||
214 | +_UpgradeReport_Files/ | ||
215 | +Backup*/ | ||
216 | +UpgradeLog*.XML | ||
217 | +UpgradeLog*.htm | ||
218 | + | ||
219 | +# SQL Server files | ||
220 | +*.mdf | ||
221 | +*.ldf | ||
222 | +*.ndf | ||
223 | + | ||
224 | +# Business Intelligence projects | ||
225 | +*.rdl.data | ||
226 | +*.bim.layout | ||
227 | +*.bim_*.settings | ||
228 | + | ||
229 | +# Microsoft Fakes | ||
230 | +FakesAssemblies/ | ||
231 | + | ||
232 | +# GhostDoc plugin setting file | ||
233 | +*.GhostDoc.xml | ||
234 | + | ||
235 | +# Node.js Tools for Visual Studio | ||
236 | +.ntvs_analysis.dat | ||
237 | +node_modules/ | ||
238 | + | ||
239 | +# Typescript v1 declaration files | ||
240 | +typings/ | ||
241 | + | ||
242 | +# Visual Studio 6 build log | ||
243 | +*.plg | ||
244 | + | ||
245 | +# Visual Studio 6 workspace options file | ||
246 | +*.opt | ||
247 | + | ||
248 | +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) | ||
249 | +*.vbw | ||
250 | + | ||
251 | +# Visual Studio LightSwitch build output | ||
252 | +**/*.HTMLClient/GeneratedArtifacts | ||
253 | +**/*.DesktopClient/GeneratedArtifacts | ||
254 | +**/*.DesktopClient/ModelManifest.xml | ||
255 | +**/*.Server/GeneratedArtifacts | ||
256 | +**/*.Server/ModelManifest.xml | ||
257 | +_Pvt_Extensions | ||
258 | + | ||
259 | +# Paket dependency manager | ||
260 | +.paket/paket.exe | ||
261 | +paket-files/ | ||
262 | + | ||
263 | +# FAKE - F# Make | ||
264 | +.fake/ | ||
265 | + | ||
266 | +# JetBrains Rider | ||
267 | +.idea/ | ||
268 | +*.sln.iml | ||
269 | + | ||
270 | +# CodeRush | ||
271 | +.cr/ | ||
272 | + | ||
273 | +# Python Tools for Visual Studio (PTVS) | ||
274 | +__pycache__/ | ||
275 | +*.pyc | ||
276 | + | ||
277 | +# Cake - Uncomment if you are using it | ||
278 | +# tools/** | ||
279 | +# !tools/packages.config | ||
280 | + | ||
281 | +# Telerik's JustMock configuration file | ||
282 | +*.jmconfig | ||
283 | + | ||
284 | +# BizTalk build output | ||
285 | +*.btp.cs | ||
286 | +*.btm.cs | ||
287 | +*.odx.cs | ||
288 | +*.xsd.cs | ||
289 | + | ||
290 | +# C++ objects and libs | ||
291 | + | ||
292 | +*.slo | ||
293 | +*.lo | ||
294 | +*.o | ||
295 | +*.a | ||
296 | +*.la | ||
297 | +*.lai | ||
298 | +*.so | ||
299 | +*.dll | ||
300 | +*.dylib | ||
301 | + | ||
302 | +# Qt-es | ||
303 | + | ||
304 | +/.qmake.cache | ||
305 | +/.qmake.stash | ||
306 | +*.pro.user | ||
307 | +*.pro.user.* | ||
308 | +*.qbs.user | ||
309 | +*.qbs.user.* | ||
310 | +*.moc | ||
311 | +moc_*.cpp | ||
312 | +qrc_*.cpp | ||
313 | +ui_*.h | ||
314 | +Makefile* | ||
315 | +*build-* | ||
316 | + | ||
317 | +# QtCreator | ||
318 | + | ||
319 | +*.autosave | ||
320 | + | ||
321 | +# QtCtreator Qml | ||
322 | +*.qmlproject.user | ||
323 | +*.qmlproject.user.* | ||
324 | + | ||
325 | +# QtCtreator CMake | ||
326 | +CMakeLists.txt.user* | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
PaperGraph/EdgeItem.cpp
0 → 100644
1 | +#include "EdgeItem.h" | ||
2 | +#include <QtWidgets> | ||
3 | + | ||
4 | +void EdgeItem::mousePressEvent(QGraphicsSceneMouseEvent * event) | ||
5 | +{ | ||
6 | +} | ||
7 | + | ||
8 | +void EdgeItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event) | ||
9 | +{ | ||
10 | +} | ||
11 | + | ||
12 | +void EdgeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * event) | ||
13 | +{ | ||
14 | +} | ||
15 | + | ||
16 | +EdgeItem::EdgeItem(double x1, double y1, double x2, double y2, QColor color, int width) | ||
17 | +{ | ||
18 | + this->x1 = x1; | ||
19 | + this->y1 = y1; | ||
20 | + this->x2 = x2; | ||
21 | + this->y2 = y2; | ||
22 | + | ||
23 | + this->color = color; | ||
24 | + this->width = width; | ||
25 | + setZValue(0); //노드 앞 가리지 않도록 ZValue 설정 | ||
26 | + | ||
27 | + /*setFlags(ItemIsSelectable | ItemIsMovable); | ||
28 | + setAcceptHoverEvents(true);*/ | ||
29 | +} | ||
30 | + | ||
31 | +QRectF EdgeItem::boundingRect() const | ||
32 | +{ | ||
33 | + return QRectF(0,0,0,0); | ||
34 | +} | ||
35 | + | ||
36 | +QPainterPath EdgeItem::shape() const | ||
37 | +{ | ||
38 | + QPainterPath path; | ||
39 | + return path; | ||
40 | +} | ||
41 | + | ||
42 | +void EdgeItem::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) | ||
43 | +{ | ||
44 | + Q_UNUSED(widget); | ||
45 | + | ||
46 | + QPen oldPen = painter->pen(); | ||
47 | + QPen pen = oldPen; | ||
48 | + pen.setWidth(width); | ||
49 | + pen.setColor(color); | ||
50 | + painter->setPen(pen); | ||
51 | + painter->drawLine(QLineF(x1, y1, x2, y2)); | ||
52 | +} |
PaperGraph/EdgeItem.h
0 → 100644
1 | +#ifndef EDGEITEM_H | ||
2 | +#define EDGEITEM_H | ||
3 | + | ||
4 | +#include <QColor> | ||
5 | +#include <QGraphicsItem> | ||
6 | + | ||
7 | + | ||
8 | +class EdgeItem | ||
9 | + : public QGraphicsItem | ||
10 | +{ | ||
11 | +private: | ||
12 | + double x1, y1, x2, y2; | ||
13 | + int width; | ||
14 | + QColor color; | ||
15 | + | ||
16 | +protected: | ||
17 | + void mousePressEvent(QGraphicsSceneMouseEvent *event) override; | ||
18 | + void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; | ||
19 | + void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; | ||
20 | + | ||
21 | +public: | ||
22 | + EdgeItem(double x1, double y1, double x2, double y2, QColor color, int width); | ||
23 | + | ||
24 | + QRectF boundingRect() const override; | ||
25 | + QPainterPath shape() const override; | ||
26 | + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; | ||
27 | +}; | ||
28 | + | ||
29 | +#endif // EDGEITEM_H | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
PaperGraph/GraphItem.cpp
0 → 100644
1 | +#include "GraphItem.h" | ||
2 | + | ||
3 | +#include <boost/graph/fruchterman_reingold.hpp> | ||
4 | +#include <boost/graph/random_layout.hpp> | ||
5 | +#include <boost/graph/circle_layout.hpp> | ||
6 | +#include <boost/graph/dijkstra_shortest_paths.hpp> | ||
7 | +#include <boost/algorithm/string.hpp> //boost::split | ||
8 | +#include <boost/bimap.hpp> | ||
9 | +#include <boost/regex.hpp> | ||
10 | + | ||
11 | +#include <exception> | ||
12 | +#include <iterator> | ||
13 | +#include <string> | ||
14 | +#include <map> | ||
15 | +#include <vector> | ||
16 | + | ||
17 | +#include <QDebug> | ||
18 | +#include <QtWidgets> | ||
19 | + | ||
20 | + | ||
21 | +GraphItem::GraphItem(ifstream& fin) | ||
22 | +{ | ||
23 | + if (!fin) | ||
24 | + throw std::exception("graph file input is invalid"); | ||
25 | + | ||
26 | + /** | ||
27 | + * Parse Paper dataset | ||
28 | + * - paper_key, [author_list], publish_year | ||
29 | + * Column Delimiter: || | ||
30 | + * Author list Delimiter: && | ||
31 | + */ | ||
32 | + std::string line; | ||
33 | + vector<std::string> tokens; | ||
34 | + vector<std::string> authors; | ||
35 | + vector<pair<string, string>> edges; | ||
36 | + | ||
37 | + //String <--> int 양방향 변환을 위해 bidirectional map 상숑 | ||
38 | + //map<string, int> -> <vertex label, vertex index> | ||
39 | + typedef boost::bimap<string, int> bm_type; | ||
40 | + bm_type node_ids; | ||
41 | + vector<simple_edge> edges_indexes; //int로 변환된 edge | ||
42 | + | ||
43 | + int node_cnt = 0; | ||
44 | + qDebug() << "* graph reading start"; | ||
45 | + | ||
46 | + //한 줄씩 읽어서 Parse | ||
47 | + while (std::getline(fin, line) && !line.empty()) { | ||
48 | + //boost::split 이용해 문자열 분리 | ||
49 | + //tokens[0]: Paper-key. ex) conf/iastedCSN/KeimS06 | ||
50 | + //tokens[1]: Authors. ex) Werner Keim&&Arpad L. Scholtz | ||
51 | + //tokens[2]: Published year. | ||
52 | + boost::split(tokens, line, boost::is_any_of("||"), boost::token_compress_on); | ||
53 | + boost::split(authors, tokens[1], boost::is_any_of("&&"), boost::token_compress_on); | ||
54 | + | ||
55 | + const string& paper_key = tokens[0]; | ||
56 | + if (node_ids.left.find(paper_key) == node_ids.left.end()) { | ||
57 | + node_ids.insert(bm_type::value_type(paper_key, node_cnt++)); | ||
58 | + } | ||
59 | + | ||
60 | + for (auto author : authors) { | ||
61 | + edges.push_back(pair<string, string>(paper_key, author)); | ||
62 | + if (node_ids.left.find(author) == node_ids.left.end()) { | ||
63 | + node_ids.insert(bm_type::value_type(author, node_cnt++)); | ||
64 | + } | ||
65 | + } | ||
66 | + | ||
67 | + //debug | ||
68 | + if (node_cnt > NODE_LIMIT) break; | ||
69 | + } | ||
70 | + qDebug() << "* graph reading complete"; | ||
71 | + qDebug() << "* # of nodes: " << node_cnt; | ||
72 | + qDebug() << "* # of edges: " << edges.size(); | ||
73 | + | ||
74 | + //edge conversion | ||
75 | + //<string, string> to <int, int> | ||
76 | + //using boost::bimap (bidirectional map) | ||
77 | + for (auto edge : edges) { | ||
78 | + edges_indexes.push_back({ | ||
79 | + node_ids.left.find(edge.first)->get_right(), | ||
80 | + node_ids.left.find(edge.second)->get_right() | ||
81 | + }); | ||
82 | + } | ||
83 | + //Graph --> defined in "PaperGraphWidget.h" | ||
84 | + //Graph graph(edges_indexes.begin(), edges_indexes.end(), node_ids.size()); | ||
85 | + graph = new Graph(edges_indexes.begin(), edges_indexes.end(), node_ids.size()); | ||
86 | + | ||
87 | + //set index property | ||
88 | + qDebug() << "* set vertex property start"; | ||
89 | + typedef typename graph_traits<Graph>::edge_iterator edge_iterator; | ||
90 | + typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator; | ||
91 | + vertex_iterator vi, vi_end; | ||
92 | + int i = 0; | ||
93 | + for (boost::tie(vi, vi_end)=vertices(*graph); vi!=vi_end; ++vi) { | ||
94 | + //Vertex Property 설정 | ||
95 | + //index: 0 ~ ... | ||
96 | + //name : map의 value(i) 기준으로 찾은 Key | ||
97 | + // map --> map<string, int> (boost bidirectional map) | ||
98 | + boost::put(vertex_index, *graph, *vi, i); | ||
99 | + boost::put(vertex_name, *graph, *vi, | ||
100 | + node_ids.right.find(i)->get_left()); | ||
101 | + | ||
102 | + ++i; | ||
103 | + } | ||
104 | + qDebug() << "* set vertex property end"; | ||
105 | + | ||
106 | + | ||
107 | + //qDebug("* set edges weight start"); | ||
108 | + ////모든 edge의 weight를 1로 설정 | ||
109 | + //typename graph_traits<Graph>::edge_iterator ei, ei_end; | ||
110 | + //for (boost::tie(ei, ei_end)=boost::edges(*graph); ei!=ei_end; ++ei) { | ||
111 | + // boost::put(edge_weight, *graph, *ei, 1); | ||
112 | + //} | ||
113 | + //qDebug("* set edges weight end"); | ||
114 | + // | ||
115 | + // | ||
116 | + //qDebug("* path highlighting start"); | ||
117 | + ////find start, end node's id | ||
118 | + //int start_idx, end_idx; | ||
119 | + //for (boost::tie(vi, vi_end)=vertices(*graph); vi!=vi_end; ++vi) { | ||
120 | + // string node_name = boost::get(vertex_name, *graph, *vi); | ||
121 | + // if (node_name == "Seong Chul Cho") { | ||
122 | + // start_idx = boost::get(vertex_index, *graph, *vi); | ||
123 | + // } else if (node_name == "Hyung Jin Kim") { | ||
124 | + // end_idx = boost::get(vertex_index, *graph, *vi); | ||
125 | + // } | ||
126 | + //} | ||
127 | + | ||
128 | + //typedef boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor; | ||
129 | + //vector<vertex_descriptor> parents(num_vertices(*graph)); | ||
130 | + //vector<int> distances(num_vertices(*graph)); | ||
131 | + //vertex_descriptor start_vertex = vertex(start_idx, *graph); | ||
132 | + //dijkstra_shortest_paths(*graph, start_vertex, | ||
133 | + // predecessor_map(&parents[0]).distance_map(&distances[0])); | ||
134 | + ////path finding | ||
135 | + //vertex_descriptor current = boost::vertex(end_idx, *graph); | ||
136 | + //while (current != boost::vertex(start_idx, *graph)) { | ||
137 | + //} | ||
138 | + //qDebug("* path highlighting end"); | ||
139 | + | ||
140 | + | ||
141 | + //graph layout calculation | ||
142 | + //using boost::random_graph_layout and boost::kamada_kawai_spring_layout | ||
143 | + //vertex마다 계산된 좌표를 property에 적용 | ||
144 | + //예제 코드: http://www.boost.org/doc/libs/1_63_0/libs/graph/test/layout_test.cpp | ||
145 | + //(-> 콘솔 기반) | ||
146 | + qDebug() << "* make graph layout start"; | ||
147 | + typedef square_topology<> Topology; | ||
148 | + minstd_rand gen; | ||
149 | + Topology topology(gen, (double)SCREEN_SIZE); | ||
150 | + Topology::point_type origin; | ||
151 | + origin[0] = origin[1] = (double)SCREEN_SIZE; | ||
152 | + Topology::point_difference_type extent; | ||
153 | + extent[0] = extent[1] = (double)SCREEN_SIZE; | ||
154 | + rectangle_topology<> rect_top(gen, | ||
155 | + -SCREEN_SIZE/2, -SCREEN_SIZE/2, | ||
156 | + SCREEN_SIZE/2, SCREEN_SIZE/2); | ||
157 | + | ||
158 | + switch (LAYOUT_MODE) { | ||
159 | + case GRAPH_LAYOUT::RANDOM_LAYOUT: | ||
160 | + random_graph_layout(*graph, get(vertex_position, *graph), rect_top); | ||
161 | + break; | ||
162 | + | ||
163 | + case GRAPH_LAYOUT::CIRCLE_LAYOUT: | ||
164 | + circle_graph_layout(*graph, get(vertex_position, *graph), SCREEN_SIZE/2); | ||
165 | + break; | ||
166 | + | ||
167 | + case GRAPH_LAYOUT::FRUCHTERMAN_REINGOLD_LAYOUT: | ||
168 | + fruchterman_reingold_force_directed_layout(*graph, | ||
169 | + get(vertex_position, *graph), | ||
170 | + topology, | ||
171 | + attractive_force(square_distance_attractive_force()) | ||
172 | + .cooling(linear_cooling<double>(50)) | ||
173 | + ); | ||
174 | + break; | ||
175 | + } | ||
176 | + qDebug() << "* make graph layout end"; | ||
177 | + | ||
178 | + | ||
179 | + //add edges | ||
180 | + typedef square_topology<> Topology; | ||
181 | + typedef typename Topology::point_type Point; | ||
182 | + auto position = get(vertex_position, *graph); | ||
183 | + auto label = get(vertex_name, *graph); | ||
184 | + | ||
185 | + typedef boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor; | ||
186 | + typename graph_traits<Graph>::edge_iterator ei, ei_end; | ||
187 | + vertex_descriptor u, v; | ||
188 | + for (boost::tie(ei, ei_end)=boost::edges(*graph); ei!=ei_end; ++ei) { | ||
189 | + u = source(*ei, *graph); | ||
190 | + v = target(*ei, *graph); | ||
191 | + Point p1 = position[u]; | ||
192 | + Point p2 = position[v]; | ||
193 | + | ||
194 | + //make edge item and push it to list | ||
195 | + EdgeItem *edge; | ||
196 | + | ||
197 | + //if (label[u] == "conf/sbrn/GomesPSRC10" || | ||
198 | + // label[u] == "conf/iastedCSN/KeimS06" || | ||
199 | + // label[v] == "conf/sbrn/GomesPSRC10" || | ||
200 | + // label[v] == "conf/iastedCSN/KeimS06") { | ||
201 | + // //highlight | ||
202 | + // edge = new EdgeItem(p1[0], p1[1], p2[0], p2[1], QColor(Qt::blue), 3); | ||
203 | + //} else { | ||
204 | + // edge = new EdgeItem(p1[0], p1[1], p2[0], p2[1], QColor(Qt::black), 0); | ||
205 | + //} | ||
206 | + edge = new EdgeItem(p1[0], p1[1], p2[0], p2[1], QColor(Qt::black), 0); | ||
207 | + edge->setPos(p1[0], p1[1]); | ||
208 | + edgeList << edge; | ||
209 | + } | ||
210 | + | ||
211 | + //add nodes | ||
212 | + for (boost::tie(vi, vi_end)=vertices(*graph); vi!=vi_end; ++vi) { | ||
213 | + Point p = position[*vi]; | ||
214 | + std::string name = label[*vi]; | ||
215 | + | ||
216 | + //make node item and push it to list | ||
217 | + NodeItem *node; | ||
218 | + //if (name == "conf/sbrn/GomesPSRC10" || | ||
219 | + // name == "conf/iastedCSN/KeimS06") { | ||
220 | + // //highlight | ||
221 | + // node = new NodeItem(p[0], p[1], QColor(Qt::blue), QString(name.c_str())); | ||
222 | + //} else { | ||
223 | + // node = new NodeItem(p[0], p[1], QColor(Qt::green), QString(name.c_str())); | ||
224 | + //} | ||
225 | + node = new NodeItem(p[0], p[1], QColor(Qt::green), QString(name.c_str())); | ||
226 | + node->setPos(QPointF(p[0], p[1])); | ||
227 | + nodeList << node; | ||
228 | + } | ||
229 | +} | ||
230 | + | ||
231 | +//override | ||
232 | +QRectF GraphItem::boundingRect() const | ||
233 | +{ | ||
234 | + //TODO | ||
235 | + return QRectF(-SCREEN_SIZE/2, -SCREEN_SIZE/2, SCREEN_SIZE, SCREEN_SIZE); | ||
236 | +} | ||
237 | + | ||
238 | +QPainterPath GraphItem::shape() const | ||
239 | +{ | ||
240 | + QPainterPath path; | ||
241 | + return path; | ||
242 | +} | ||
243 | + | ||
244 | +void GraphItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) | ||
245 | +{ | ||
246 | + if (!graph) | ||
247 | + return; | ||
248 | + | ||
249 | + //debug | ||
250 | + //-> x, y, w, h | ||
251 | + //현재 Graph의 bounding rect 출력 | ||
252 | + /*QPen oldPen = painter->pen(); | ||
253 | + QPen pen = oldPen; | ||
254 | + pen.setColor(Qt::red); | ||
255 | + painter->setPen(pen); | ||
256 | + painter->drawRect(QRectF(-SCREEN_SIZE/2, -SCREEN_SIZE/2, SCREEN_SIZE, SCREEN_SIZE));*/ | ||
257 | + | ||
258 | + //print edges | ||
259 | + for (auto edge: edgeList) { | ||
260 | + edge->paint(painter, option, widget); | ||
261 | + } | ||
262 | + | ||
263 | + //print nodes | ||
264 | + for (auto node: nodeList) { | ||
265 | + node->paint(painter, option, widget); | ||
266 | + } | ||
267 | +} | ||
268 | + | ||
269 | +//event handler | ||
270 | +void GraphItem::mousePressEvent(QGraphicsSceneMouseEvent *event) | ||
271 | +{ | ||
272 | +} | ||
273 | + | ||
274 | +void GraphItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) | ||
275 | +{ | ||
276 | +} | ||
277 | + | ||
278 | +void GraphItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) | ||
279 | +{ | ||
280 | +} |
PaperGraph/GraphItem.h
0 → 100644
1 | +#ifndef GRAPHITEM_H | ||
2 | +#define GRAPHITEM_H | ||
3 | + | ||
4 | +#include <QGraphicsItem> | ||
5 | +#include <QList> | ||
6 | +#include <QColor> | ||
7 | + | ||
8 | +#include <boost/graph/adjacency_list.hpp> | ||
9 | +#include <boost/graph/topology.hpp> | ||
10 | +#include <boost/graph/graph_traits.hpp> | ||
11 | + | ||
12 | +#include <fstream> | ||
13 | + | ||
14 | +#include "NodeItem.h" | ||
15 | +#include "EdgeItem.h" | ||
16 | + | ||
17 | +using namespace std; | ||
18 | +using namespace boost; | ||
19 | + | ||
20 | + | ||
21 | +enum GRAPH_LAYOUT { | ||
22 | + RANDOM_LAYOUT, | ||
23 | + CIRCLE_LAYOUT, | ||
24 | + //KAMADA_KAWAI_LAYOUT, | ||
25 | + FRUCHTERMAN_REINGOLD_LAYOUT //slow | ||
26 | +}; | ||
27 | +/** | ||
28 | + * Constants | ||
29 | + */ | ||
30 | +const int LAYOUT_MODE = GRAPH_LAYOUT::RANDOM_LAYOUT; | ||
31 | +const int SCREEN_SIZE = 300; | ||
32 | +const int NODE_LIMIT = 100; | ||
33 | + | ||
34 | + | ||
35 | +enum vertex_position_t { vertex_position }; | ||
36 | +namespace boost { | ||
37 | + BOOST_INSTALL_PROPERTY(vertex, position); | ||
38 | +} | ||
39 | +typedef square_topology<>::point_type point; | ||
40 | +struct simple_edge { | ||
41 | + int first, second; | ||
42 | +}; | ||
43 | +typedef boost::property<vertex_index_t, int, | ||
44 | + boost::property<vertex_name_t, std::string, | ||
45 | + boost::property<vertex_position_t, point>> | ||
46 | +> VertexProperties; | ||
47 | +typedef adjacency_list< | ||
48 | + listS, //outEdgeList | ||
49 | + listS, //VertexList | ||
50 | + undirectedS, | ||
51 | + //vertex properties | ||
52 | + VertexProperties, | ||
53 | + //edge properties | ||
54 | + boost::property<edge_weight_t, double> | ||
55 | +> Graph; | ||
56 | + | ||
57 | + | ||
58 | +class GraphItem | ||
59 | + : public QGraphicsItem | ||
60 | +{ | ||
61 | +public: | ||
62 | + GraphItem(ifstream& fin); | ||
63 | + | ||
64 | + //overrides | ||
65 | + QRectF boundingRect() const override; | ||
66 | + QPainterPath shape() const override; | ||
67 | + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; | ||
68 | + | ||
69 | + //methods | ||
70 | + void path_highlighting(std::string start, std::string end); | ||
71 | + // | ||
72 | + | ||
73 | +protected: | ||
74 | + void mousePressEvent(QGraphicsSceneMouseEvent *event) override; | ||
75 | + void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; | ||
76 | + void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; | ||
77 | + | ||
78 | +private: | ||
79 | + Graph *graph = nullptr; | ||
80 | + QList<NodeItem *> nodeList; | ||
81 | + QList<EdgeItem *> edgeList; | ||
82 | +}; | ||
83 | + | ||
84 | +#endif // GRAPHITEM_H |
1 | #include "GraphicsView.h" | 1 | #include "GraphicsView.h" |
2 | #include <qmath.h> | 2 | #include <qmath.h> |
3 | +#include <QKeyEvent> | ||
3 | 4 | ||
4 | //View | 5 | //View |
5 | View::View(const QString& name, QWidget *parent) | 6 | View::View(const QString& name, QWidget *parent) |
... | @@ -12,8 +13,6 @@ View::View(const QString& name, QWidget *parent) | ... | @@ -12,8 +13,6 @@ View::View(const QString& name, QWidget *parent) |
12 | graphicsView->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate); | 13 | graphicsView->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate); |
13 | graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse); | 14 | graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse); |
14 | 15 | ||
15 | - //connect | ||
16 | - | ||
17 | //layout | 16 | //layout |
18 | QGridLayout *topLayout = new QGridLayout; | 17 | QGridLayout *topLayout = new QGridLayout; |
19 | topLayout->addWidget(graphicsView, 0, 0); | 18 | topLayout->addWidget(graphicsView, 0, 0); |
... | @@ -29,11 +28,27 @@ QGraphicsView* View::view() const | ... | @@ -29,11 +28,27 @@ QGraphicsView* View::view() const |
29 | 28 | ||
30 | void View::setupMatrix() | 29 | void View::setupMatrix() |
31 | { | 30 | { |
32 | - qreal scale = qPow(qreal(2), qreal(2)); | 31 | + qreal scale = qPow(qreal(1), qreal(1)); |
33 | 32 | ||
34 | QMatrix matrix; | 33 | QMatrix matrix; |
35 | matrix.scale(scale, scale); | 34 | matrix.scale(scale, scale); |
36 | matrix.rotate(qreal(0)); | 35 | matrix.rotate(qreal(0)); |
37 | 36 | ||
38 | graphicsView->setMatrix(matrix); | 37 | graphicsView->setMatrix(matrix); |
39 | -} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
38 | +} | ||
39 | + | ||
40 | +#ifndef QT_NO_WHEELEVENT | ||
41 | +void GraphicsView::wheelEvent(QWheelEvent * event) | ||
42 | +{ | ||
43 | + scaleView(pow((double)2, event->delta() / 240.0)); | ||
44 | +} | ||
45 | +#endif | ||
46 | + | ||
47 | +void GraphicsView::scaleView(qreal scaleFactor) | ||
48 | +{ | ||
49 | + qreal factor = transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width(); | ||
50 | + if (factor < 0.07 || factor > 100) | ||
51 | + return; | ||
52 | + | ||
53 | + scale(scaleFactor, scaleFactor); | ||
54 | +} | ... | ... |
... | @@ -16,6 +16,12 @@ class GraphicsView | ... | @@ -16,6 +16,12 @@ class GraphicsView |
16 | private: | 16 | private: |
17 | View* view; | 17 | View* view; |
18 | 18 | ||
19 | +protected: | ||
20 | +#ifndef QT_NO_WHEELEVENT | ||
21 | + void wheelEvent(QWheelEvent *event) override; | ||
22 | +#endif | ||
23 | + void scaleView(qreal scaleFactor); | ||
24 | + | ||
19 | public: | 25 | public: |
20 | GraphicsView(View *v): QGraphicsView(), view(v) {}; | 26 | GraphicsView(View *v): QGraphicsView(), view(v) {}; |
21 | }; | 27 | }; | ... | ... |
1 | #include "NodeItem.h" | 1 | #include "NodeItem.h" |
2 | #include <QtWidgets> | 2 | #include <QtWidgets> |
3 | +#include <QMessageBox> | ||
3 | 4 | ||
4 | void NodeItem::mousePressEvent(QGraphicsSceneMouseEvent * event) | 5 | void NodeItem::mousePressEvent(QGraphicsSceneMouseEvent * event) |
5 | { | 6 | { |
7 | + /*if (event->button() == Qt::LeftButton) { | ||
8 | + QMessageBox msgbox; | ||
9 | + msgbox.setText("hi"); | ||
10 | + msgbox.setInformativeText("hi2"); | ||
11 | + msgbox.setStandardButtons(QMessageBox::Ok); | ||
12 | + msgbox.setDefaultButton(QMessageBox::Ok); | ||
13 | + | ||
14 | + msgbox.exec(); | ||
15 | + }*/ | ||
6 | } | 16 | } |
7 | 17 | ||
8 | void NodeItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event) | 18 | void NodeItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event) |
... | @@ -13,16 +23,17 @@ void NodeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * event) | ... | @@ -13,16 +23,17 @@ void NodeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * event) |
13 | { | 23 | { |
14 | } | 24 | } |
15 | 25 | ||
16 | -NodeItem::NodeItem(int x, int y, QString label) | 26 | +NodeItem::NodeItem(double x, double y, QColor color, QString label) |
17 | { | 27 | { |
28 | + //node constructor | ||
18 | this->x = x; | 29 | this->x = x; |
19 | this->y = y; | 30 | this->y = y; |
20 | - this->color = QColor(Qt::green); | 31 | + this->color = color; |
21 | this->label = label; | 32 | this->label = label; |
22 | setZValue(1); | 33 | setZValue(1); |
23 | 34 | ||
24 | - setFlags(ItemIsSelectable | ItemIsMovable); | 35 | + //setFlags(ItemIsSelectable | ItemIsMovable); |
25 | - setAcceptHoverEvents(true); | 36 | + //setAcceptHoverEvents(true); |
26 | } | 37 | } |
27 | 38 | ||
28 | QRectF NodeItem::boundingRect() const | 39 | QRectF NodeItem::boundingRect() const |
... | @@ -33,7 +44,6 @@ QRectF NodeItem::boundingRect() const | ... | @@ -33,7 +44,6 @@ QRectF NodeItem::boundingRect() const |
33 | QPainterPath NodeItem::shape() const | 44 | QPainterPath NodeItem::shape() const |
34 | { | 45 | { |
35 | QPainterPath path; | 46 | QPainterPath path; |
36 | - //path.addRect(14, 14, 82, 42); | ||
37 | path.addRect(0, 0, NODE_SIZE, NODE_SIZE); | 47 | path.addRect(0, 0, NODE_SIZE, NODE_SIZE); |
38 | return path; | 48 | return path; |
39 | } | 49 | } |
... | @@ -42,23 +52,24 @@ void NodeItem::paint(QPainter * painter, const QStyleOptionGraphicsItem * option | ... | @@ -42,23 +52,24 @@ void NodeItem::paint(QPainter * painter, const QStyleOptionGraphicsItem * option |
42 | { | 52 | { |
43 | Q_UNUSED(widget); | 53 | Q_UNUSED(widget); |
44 | 54 | ||
55 | + //set node pen style | ||
56 | + QPen oldPen = painter->pen(); | ||
57 | + QPen pen = oldPen; | ||
58 | + pen.setWidth(0); | ||
59 | + pen.setColor(QColor(Qt::black)); | ||
60 | + painter->setPen(pen); | ||
61 | + | ||
45 | //label | 62 | //label |
46 | - QFont font("Gulim", 10); | 63 | + QFont font("Gulim", 3); //set font, font size |
47 | - font.setStyleStrategy(QFont::ForceOutline); | ||
48 | painter->setFont(font); | 64 | painter->setFont(font); |
49 | painter->save(); | 65 | painter->save(); |
50 | - painter->scale(0.3, 0.3); | 66 | + painter->drawText(x, y, label); |
51 | - painter->drawText(0, 0, label); | ||
52 | painter->restore(); | 67 | painter->restore(); |
53 | 68 | ||
54 | 69 | ||
55 | - //Rectangle | 70 | + //node rectangle |
56 | QColor fillColor = (option->state & QStyle::State_Selected) ? color.dark(150) : color; | 71 | QColor fillColor = (option->state & QStyle::State_Selected) ? color.dark(150) : color; |
57 | if (option->state & QStyle::State_MouseOver) fillColor = fillColor.light(125); | 72 | if (option->state & QStyle::State_MouseOver) fillColor = fillColor.light(125); |
58 | - QPen pen = painter->pen(); | ||
59 | - pen.setWidth(0); | ||
60 | - pen.setColor(QColor(Qt::black)); | ||
61 | - painter->setPen(pen); | ||
62 | painter->setBrush(QBrush(fillColor)); | 73 | painter->setBrush(QBrush(fillColor)); |
63 | - painter->drawRect(0, 0, NODE_SIZE, NODE_SIZE); | 74 | + painter->drawRect(x, y, NODE_SIZE, NODE_SIZE); |
64 | } | 75 | } | ... | ... |
... | @@ -11,8 +11,8 @@ class NodeItem | ... | @@ -11,8 +11,8 @@ class NodeItem |
11 | : public QGraphicsItem | 11 | : public QGraphicsItem |
12 | { | 12 | { |
13 | private: | 13 | private: |
14 | - int x; | 14 | + double x; |
15 | - int y; | 15 | + double y; |
16 | QColor color; | 16 | QColor color; |
17 | QString label; | 17 | QString label; |
18 | 18 | ||
... | @@ -22,7 +22,7 @@ protected: | ... | @@ -22,7 +22,7 @@ protected: |
22 | void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; | 22 | void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; |
23 | 23 | ||
24 | public: | 24 | public: |
25 | - NodeItem(int x, int y, QString label); | 25 | + NodeItem(double x, double y, QColor color, QString label); |
26 | 26 | ||
27 | QRectF boundingRect() const override; | 27 | QRectF boundingRect() const override; |
28 | 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> |
... | @@ -172,6 +173,7 @@ | ... | @@ -172,6 +173,7 @@ |
172 | <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | 173 | <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> |
173 | </ClCompile> | 174 | </ClCompile> |
174 | <ClCompile Include="GraphicsView.cpp" /> | 175 | <ClCompile Include="GraphicsView.cpp" /> |
176 | + <ClCompile Include="GraphItem.cpp" /> | ||
175 | <ClCompile Include="main.cpp" /> | 177 | <ClCompile Include="main.cpp" /> |
176 | <ClCompile Include="NodeItem.cpp" /> | 178 | <ClCompile Include="NodeItem.cpp" /> |
177 | <ClCompile Include="PaperGraphWidget.cpp" /> | 179 | <ClCompile Include="PaperGraphWidget.cpp" /> |
... | @@ -217,6 +219,7 @@ | ... | @@ -217,6 +219,7 @@ |
217 | </CustomBuild> | 219 | </CustomBuild> |
218 | </ItemGroup> | 220 | </ItemGroup> |
219 | <ItemGroup> | 221 | <ItemGroup> |
222 | + <ClInclude Include="EdgeItem.h" /> | ||
220 | <ClInclude Include="GeneratedFiles\ui_PaperGraphWidget.h" /> | 223 | <ClInclude Include="GeneratedFiles\ui_PaperGraphWidget.h" /> |
221 | <CustomBuild Include="GraphicsView.h"> | 224 | <CustomBuild Include="GraphicsView.h"> |
222 | <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs> | 225 | <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs> |
... | @@ -236,6 +239,7 @@ | ... | @@ -236,6 +239,7 @@ |
236 | <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs> | 239 | <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs> |
237 | <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets"</Command> | 240 | <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets"</Command> |
238 | </CustomBuild> | 241 | </CustomBuild> |
242 | + <ClInclude Include="GraphItem.h" /> | ||
239 | <ClInclude Include="NodeItem.h" /> | 243 | <ClInclude Include="NodeItem.h" /> |
240 | </ItemGroup> | 244 | </ItemGroup> |
241 | <ItemGroup> | 245 | <ItemGroup> | ... | ... |
... | @@ -62,6 +62,12 @@ | ... | @@ -62,6 +62,12 @@ |
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="GraphItem.cpp"> | ||
66 | + <Filter>Source Files</Filter> | ||
67 | + </ClCompile> | ||
68 | + <ClCompile Include="EdgeItem.cpp"> | ||
69 | + <Filter>Source Files</Filter> | ||
70 | + </ClCompile> | ||
65 | </ItemGroup> | 71 | </ItemGroup> |
66 | <ItemGroup> | 72 | <ItemGroup> |
67 | <CustomBuild Include="PaperGraphWidget.h"> | 73 | <CustomBuild Include="PaperGraphWidget.h"> |
... | @@ -84,5 +90,11 @@ | ... | @@ -84,5 +90,11 @@ |
84 | <ClInclude Include="NodeItem.h"> | 90 | <ClInclude Include="NodeItem.h"> |
85 | <Filter>Header Files</Filter> | 91 | <Filter>Header Files</Filter> |
86 | </ClInclude> | 92 | </ClInclude> |
93 | + <ClInclude Include="GraphItem.h"> | ||
94 | + <Filter>Header Files</Filter> | ||
95 | + </ClInclude> | ||
96 | + <ClInclude Include="EdgeItem.h"> | ||
97 | + <Filter>Header Files</Filter> | ||
98 | + </ClInclude> | ||
87 | </ItemGroup> | 99 | </ItemGroup> |
88 | </Project> | 100 | </Project> |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -3,6 +3,9 @@ | ... | @@ -3,6 +3,9 @@ |
3 | #include "GraphicsView.h" | 3 | #include "GraphicsView.h" |
4 | 4 | ||
5 | #include <string> | 5 | #include <string> |
6 | +#include <QComboBox> | ||
7 | +#include <QMessageBox> | ||
8 | +#include <QtGui> | ||
6 | 9 | ||
7 | PaperGraphWidget::PaperGraphWidget(QWidget *parent) | 10 | PaperGraphWidget::PaperGraphWidget(QWidget *parent) |
8 | : QWidget(parent) | 11 | : QWidget(parent) |
... | @@ -12,77 +15,40 @@ PaperGraphWidget::PaperGraphWidget(QWidget *parent) | ... | @@ -12,77 +15,40 @@ PaperGraphWidget::PaperGraphWidget(QWidget *parent) |
12 | 15 | ||
13 | View *view = new View("temp view"); | 16 | View *view = new View("temp view"); |
14 | view->view()->setScene(scene); | 17 | view->view()->setScene(scene); |
15 | - QHBoxLayout *layout = new QHBoxLayout; | 18 | + |
19 | + QVBoxLayout *layout = new QVBoxLayout; | ||
20 | + QComboBox *combo = new QComboBox; | ||
21 | + combo->addItem("conf/iastedCSN/KeimS06"); | ||
22 | + combo->addItem("conf/iastedCSN/Mojumdar06"); | ||
23 | + combo->addItem("conf/iastedCSN/PourKKI06"); | ||
24 | + connect(combo, SIGNAL(currentIndexChanged(int)), | ||
25 | + this, SLOT(handleSelectionChanged(int))); | ||
26 | + | ||
27 | + layout->addWidget(combo); | ||
16 | layout->addWidget(view); | 28 | layout->addWidget(view); |
17 | setLayout(layout); | 29 | setLayout(layout); |
18 | 30 | ||
19 | setWindowTitle(tr("dblp paper graph visualization")); | 31 | setWindowTitle(tr("dblp paper graph visualization")); |
20 | } | 32 | } |
21 | 33 | ||
22 | -void PaperGraphWidget::print_graph(const Graph & graph) | 34 | +void PaperGraphWidget::print_graph(ifstream& fin) |
23 | { | 35 | { |
24 | - //print graph | 36 | + QGraphicsItem *graph_item = new GraphItem(fin); |
25 | - typedef square_topology<> Topology; | 37 | + graph_item->setPos(0, 0); |
26 | - typedef typename Topology::point_type Point; | 38 | + scene->addItem(graph_item); |
27 | - const int rect_sz = 4; | 39 | +} |
28 | - auto position = get(vertex_position, graph); | ||
29 | - auto label = get(vertex_name, graph); | ||
30 | - | ||
31 | - | ||
32 | - | ||
33 | - //print edges | ||
34 | - typename graph_traits<Graph>::edge_iterator ei, ei_end; | ||
35 | - typedef boost::graph_traits<Graph>::vertex_descriptor VertexDescriptor; | ||
36 | - VertexDescriptor u, v; | ||
37 | - for (boost::tie(ei, ei_end)=edges(graph); ei!=ei_end; ++ei) { | ||
38 | - u = source(*ei, graph); | ||
39 | - v = target(*ei, graph); | ||
40 | - | ||
41 | - Point p1 = position[u]; | ||
42 | - Point p2 = position[v]; | ||
43 | - | ||
44 | - /*line = scene->addLine( | ||
45 | - p1[0], p1[1], | ||
46 | - p2[0], p2[1], | ||
47 | - QPen(Qt::black) | ||
48 | - );*/ | ||
49 | - //QGraphicsItem *edge = | ||
50 | - // new EdgeItem(p1[0], p1[1], p2[0], p2[1]); | ||
51 | - //edge->setPos(QPointF(p1[0], p1[1])); | ||
52 | - //scene->addItem(edge); | ||
53 | - | ||
54 | - scene->addLine(p1[0], p1[1], p2[0], p2[1], QPen(Qt::black, 0)); | ||
55 | - } | ||
56 | 40 | ||
57 | - //print nodes | 41 | +void PaperGraphWidget::handleSelectionChanged(int idx) |
58 | - typename graph_traits<Graph>::vertex_iterator vi, vi_end; | 42 | +{ |
59 | - for (boost::tie(vi, vi_end)=vertices(graph); vi!=vi_end; ++vi) { | 43 | + /*QMessageBox::information(this, "QCombobox", |
60 | - //Point p = position[*vi]; | 44 | + "idx: "+QString::number(idx));*/ |
61 | - //rectangle = scene->addRect( | 45 | + if (idx==0) { |
62 | - // p[0], p[1], rect_sz, rect_sz, | 46 | + } else if (idx==1) { |
63 | - // QPen(Qt::black), | 47 | + } else { |
64 | - // QBrush(Qt::green)); | ||
65 | - Point p = position[*vi]; | ||
66 | - std::string name = label[*vi]; | ||
67 | - QGraphicsItem *node = new NodeItem(p[0], p[1], QString(name.c_str())); | ||
68 | - node->setPos(QPointF(p[0], p[1])); | ||
69 | - scene->addItem(node); | ||
70 | } | 48 | } |
71 | } | 49 | } |
72 | 50 | ||
73 | void PaperGraphWidget::initscene() | 51 | void PaperGraphWidget::initscene() |
74 | { | 52 | { |
75 | scene = new QGraphicsScene(this); | 53 | scene = new QGraphicsScene(this); |
76 | - | ||
77 | - //int x = 0, y; | ||
78 | - //for (int i=-11000; i<11000; i+=110) { | ||
79 | - // ++x; | ||
80 | - // y = 0; | ||
81 | - // for (int j=-7000; j<7000; j+=70) { | ||
82 | - // ++y; | ||
83 | - // QGraphicsItem *item = new NodeItem(x, y); | ||
84 | - // item->setPos(QPointF(i, j)); | ||
85 | - // scene->addItem(item); | ||
86 | - // } | ||
87 | - //} | ||
88 | } | 54 | } | ... | ... |
... | @@ -4,46 +4,22 @@ | ... | @@ -4,46 +4,22 @@ |
4 | #include <QtWidgets/QWidget> | 4 | #include <QtWidgets/QWidget> |
5 | #include <QGraphicsScene> | 5 | #include <QGraphicsScene> |
6 | 6 | ||
7 | -#include <boost/graph/adjacency_list.hpp> | 7 | +#include <fstream> |
8 | -#include <boost/graph/topology.hpp> | ||
9 | -#include <boost/graph/graph_traits.hpp> | ||
10 | 8 | ||
9 | +#include "GraphItem.h" | ||
11 | #include "ui_PaperGraphWidget.h" | 10 | #include "ui_PaperGraphWidget.h" |
12 | 11 | ||
13 | 12 | ||
14 | -using namespace boost; | ||
15 | - | ||
16 | - | ||
17 | -enum vertex_position_t { vertex_position }; | ||
18 | -namespace boost { | ||
19 | - BOOST_INSTALL_PROPERTY(vertex, position); | ||
20 | -} | ||
21 | -typedef square_topology<>::point_type point; | ||
22 | -struct simple_edge { | ||
23 | - int first, second; | ||
24 | -}; | ||
25 | -typedef boost::property<vertex_index_t, int, | ||
26 | - boost::property<vertex_name_t, std::string, | ||
27 | - boost::property<vertex_position_t, point>> | ||
28 | -> VertexProperties; | ||
29 | -typedef adjacency_list< | ||
30 | - listS, //outEdgeList | ||
31 | - listS, //VertexList | ||
32 | - undirectedS, | ||
33 | - //vertex properties | ||
34 | - VertexProperties, | ||
35 | - //edge properties | ||
36 | - boost::property<edge_weight_t, double> | ||
37 | -> Graph; | ||
38 | - | ||
39 | - | ||
40 | class PaperGraphWidget : public QWidget | 13 | class PaperGraphWidget : public QWidget |
41 | { | 14 | { |
42 | Q_OBJECT | 15 | Q_OBJECT |
43 | 16 | ||
44 | public: | 17 | public: |
45 | PaperGraphWidget(QWidget *parent = 0); | 18 | PaperGraphWidget(QWidget *parent = 0); |
46 | - void print_graph(const Graph& graph); | 19 | + void print_graph(ifstream& fin); |
20 | + | ||
21 | +private slots: | ||
22 | + void handleSelectionChanged(int idx); | ||
47 | 23 | ||
48 | private: | 24 | private: |
49 | void initscene(); | 25 | void initscene(); | ... | ... |
... | @@ -14,7 +14,6 @@ | ... | @@ -14,7 +14,6 @@ |
14 | //#include <boost/graph/kamada_kawai_spring_layout.hpp> | 14 | //#include <boost/graph/kamada_kawai_spring_layout.hpp> |
15 | #include <boost/graph/random_layout.hpp> | 15 | #include <boost/graph/random_layout.hpp> |
16 | #include <boost/graph/circle_layout.hpp> | 16 | #include <boost/graph/circle_layout.hpp> |
17 | -#include <boost/graph/dijkstra_shortest_paths.hpp> | ||
18 | #include <boost/algorithm/string.hpp> //boost::split | 17 | #include <boost/algorithm/string.hpp> //boost::split |
19 | #include <boost/bimap.hpp> | 18 | #include <boost/bimap.hpp> |
20 | 19 | ||
... | @@ -24,187 +23,22 @@ using namespace std; | ... | @@ -24,187 +23,22 @@ using namespace std; |
24 | * Constants | 23 | * Constants |
25 | */ | 24 | */ |
26 | const char* PAPER_FILENAME = "dblp-paper.txt"; | 25 | 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; | ||
36 | - | ||
37 | -Graph read_graph(ifstream& in) throw(std::exception) { | ||
38 | - /** | ||
39 | - * Parse Paper dataset | ||
40 | - * - paper_key, [author_list], publish_year | ||
41 | - * Column Delimiter: || | ||
42 | - * Author list Delimiter: && | ||
43 | - */ | ||
44 | - std::string line; | ||
45 | - vector<std::string> tokens; | ||
46 | - vector<std::string> authors; | ||
47 | - vector<pair<string, string>> edges; | ||
48 | - | ||
49 | - //String <--> int 양방향 변환을 위해 bidirectional map 상숑 | ||
50 | - //map<string, int> -> <vertex label, vertex index> | ||
51 | - typedef boost::bimap<string, int> bm_type; | ||
52 | - bm_type node_ids; | ||
53 | - vector<simple_edge> edges_indexes; //int로 변환된 edge | ||
54 | - | ||
55 | - int node_cnt = 0; | ||
56 | - qDebug() << "* graph reading start"; | ||
57 | - | ||
58 | - //한 줄씩 읽어서 Parse | ||
59 | - while (std::getline(in, line) && !line.empty()) { | ||
60 | - //boost::split 이용해 문자열 분리 | ||
61 | - //tokens[0]: Paper-key. ex) conf/iastedCSN/KeimS06 | ||
62 | - //tokens[1]: Authors. ex) Werner Keim&&Arpad L. Scholtz | ||
63 | - //tokens[2]: Published year. | ||
64 | - boost::split(tokens, line, boost::is_any_of("||"), boost::token_compress_on); | ||
65 | - boost::split(authors, tokens[1], boost::is_any_of("&&"), boost::token_compress_on); | ||
66 | - | ||
67 | - const string& paper_key = tokens[0]; | ||
68 | - if (node_ids.left.find(paper_key) == node_ids.left.end()) { | ||
69 | - node_ids.insert(bm_type::value_type(paper_key, node_cnt++)); | ||
70 | - } | ||
71 | - | ||
72 | - for (auto author : authors) { | ||
73 | - edges.push_back(pair<string, string>(paper_key, author)); | ||
74 | - if (node_ids.left.find(author) == node_ids.left.end()) { | ||
75 | - node_ids.insert(bm_type::value_type(author, node_cnt++)); | ||
76 | - } | ||
77 | - } | ||
78 | - | ||
79 | - //debug | ||
80 | - if (node_cnt > NODE_LIMIT) break; | ||
81 | - } | ||
82 | - qDebug() << "* graph reading complete"; | ||
83 | - qDebug() << "* # of nodes: " << node_cnt; | ||
84 | - qDebug() << "* # of edges: " << edges.size(); | ||
85 | - | ||
86 | - //edge conversion | ||
87 | - //<string, string> to <int, int> | ||
88 | - //using boost::bimap (bidirectional map) | ||
89 | - for (auto edge : edges) { | ||
90 | - edges_indexes.push_back({ | ||
91 | - node_ids.left.find(edge.first)->get_right(), | ||
92 | - node_ids.left.find(edge.second)->get_right() | ||
93 | - }); | ||
94 | - } | ||
95 | - //Graph --> defined in "PaperGraphWidget.h" | ||
96 | - Graph graph(edges_indexes.begin(), edges_indexes.end(), node_ids.size()); | ||
97 | - | ||
98 | - //set index property | ||
99 | - qDebug() << "* set vertex property start"; | ||
100 | - typedef typename graph_traits<Graph>::edge_iterator edge_iterator; | ||
101 | - typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator; | ||
102 | - vertex_iterator vi, vi_end; | ||
103 | - int i = 0; | ||
104 | - for (boost::tie(vi, vi_end)=vertices(graph); vi!=vi_end; ++vi) { | ||
105 | - //Vertex Property 설정 | ||
106 | - //index: 0 ~ ... | ||
107 | - //name : map의 value(i) 기준으로 찾은 Key | ||
108 | - // map --> map<string, int> (boost bidirectional map) | ||
109 | - boost::put(vertex_index, graph, *vi, i); | ||
110 | - boost::put(vertex_name, graph, *vi, | ||
111 | - node_ids.right.find(i)->get_left()); | ||
112 | - | ||
113 | - ++i; | ||
114 | - } | ||
115 | - qDebug() << "* set vertex property end"; | ||
116 | - | ||
117 | - | ||
118 | - //모든 edge weight 1로 만들기 | ||
119 | - //edge_iterator ei, ei_end; | ||
120 | - //for (boost::tie(ei, ei_end)=boost::edges(graph); ei!=ei_end; ++ei) { | ||
121 | - // boost::put(edge_weight, graph, *ei, 1); | ||
122 | - //} | ||
123 | - ////path finding between two vertices | ||
124 | - ////using dijkstra algorithm | ||
125 | - ////ex) "Werner Keim" ---> "Arpad L. Scholtz" (in dataset 2nd line) | ||
126 | - //qDebug() << "* path finding start"; | ||
127 | - //typedef graph_traits<Graph>::vertex_descriptor vertex_descriptor; | ||
128 | - //std::vector<vertex_descriptor> parent(num_vertices(graph)); | ||
129 | - //std::vector<int> distance(num_vertices(graph)); | ||
130 | - //int start_idx = node_ids.left.find("Werner Keim")->get_right(); | ||
131 | - //vertex_descriptor start_v = vertex(start_idx, graph); | ||
132 | - //dijkstra_shortest_paths( | ||
133 | - // graph, | ||
134 | - // start_v, | ||
135 | - // predecessor_map( | ||
136 | - // boost::make_iterator_property_map(parent.begin(), get(boost::vertex_index, graph)) | ||
137 | - // ).distance_map(boost::make_iterator_property_map(distance.begin(), get(boost::vertex_index, graph))) | ||
138 | - //); | ||
139 | - //qDebug() << "* path finding end"; | ||
140 | - | ||
141 | - | ||
142 | - //graph layout calculation | ||
143 | - //using boost::random_graph_layout and boost::kamada_kawai_spring_layout | ||
144 | - //vertex마다 계산된 좌표를 property에 적용 | ||
145 | - //예제 코드: http://www.boost.org/doc/libs/1_63_0/libs/graph/test/layout_test.cpp | ||
146 | - //(-> 콘솔 기반) | ||
147 | - qDebug() << "* make graph layout start"; | ||
148 | - typedef square_topology<> Topology; | ||
149 | - minstd_rand gen; | ||
150 | - Topology topology(gen, (double)SCREEN_SIZE); | ||
151 | - Topology::point_type origin; | ||
152 | - origin[0] = origin[1] = (double)SCREEN_SIZE; | ||
153 | - Topology::point_difference_type extent; | ||
154 | - extent[0] = extent[1] = (double)SCREEN_SIZE; | ||
155 | - rectangle_topology<> rect_top(gen, | ||
156 | - -SCREEN_SIZE/2, -SCREEN_SIZE/2, | ||
157 | - SCREEN_SIZE/2, SCREEN_SIZE/2); | ||
158 | - | ||
159 | - switch (LAYOUT_MODE) { | ||
160 | - case GRAPH_LAYOUT::RANDOM_LAYOUT: | ||
161 | - random_graph_layout(graph, get(vertex_position, graph), rect_top); | ||
162 | - break; | ||
163 | - | ||
164 | - case GRAPH_LAYOUT::CIRCLE_LAYOUT: | ||
165 | - circle_graph_layout(graph, get(vertex_position, graph), SCREEN_SIZE/2); | ||
166 | - break; | ||
167 | - | ||
168 | - //case GRAPH_LAYOUT::KAMADA_KAWAI_LAYOUT: | ||
169 | - // kamada_kawai_spring_layout(graph, | ||
170 | - // get(vertex_position, graph), | ||
171 | - // get(edge_weight, graph), | ||
172 | - // topology, | ||
173 | - // side_length((double)SCREEN_SIZE) | ||
174 | - // ); | ||
175 | - // break; | ||
176 | - | ||
177 | - case GRAPH_LAYOUT::FRUCHTERMAN_REINGOLD_LAYOUT: | ||
178 | - fruchterman_reingold_force_directed_layout(graph, | ||
179 | - get(vertex_position, graph), | ||
180 | - topology, | ||
181 | - attractive_force(square_distance_attractive_force()) | ||
182 | - .cooling(linear_cooling<double>(50)) | ||
183 | - ); | ||
184 | - break; | ||
185 | - } | ||
186 | - qDebug() << "* make graph layout end"; | ||
187 | - | ||
188 | - return graph; | ||
189 | -} | ||
190 | 26 | ||
191 | int main(int argc, char *argv[]) | 27 | int main(int argc, char *argv[]) |
192 | { | 28 | { |
193 | QApplication app(argc, argv); | 29 | QApplication app(argc, argv); |
194 | - //app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); | ||
195 | 30 | ||
196 | PaperGraphWidget w; | 31 | PaperGraphWidget w; |
197 | 32 | ||
198 | try { | 33 | try { |
199 | ifstream fin(PAPER_FILENAME); | 34 | ifstream fin(PAPER_FILENAME); |
200 | - w.print_graph(read_graph(fin)); | 35 | + w.print_graph(fin); |
201 | fin.close(); | 36 | fin.close(); |
202 | } catch (const std::exception& e) { | 37 | } catch (const std::exception& e) { |
203 | qDebug() << "Error: " << e.what(); | 38 | qDebug() << "Error: " << e.what(); |
204 | return EXIT_FAILURE; | 39 | return EXIT_FAILURE; |
205 | } | 40 | } |
206 | 41 | ||
207 | - | ||
208 | w.show(); | 42 | w.show(); |
209 | 43 | ||
210 | return app.exec(); | 44 | return app.exec(); | ... | ... |
-
Please register or login to post a comment