rgl 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +74 -0
- data/Makefile +72 -0
- data/README +240 -0
- data/Rakefile +210 -0
- data/TAGS +209 -0
- data/examples/canvas.rb +103 -0
- data/examples/codegraph +238 -0
- data/examples/example.jpg +0 -0
- data/examples/examples.rb +112 -0
- data/examples/graph.dot +54 -0
- data/examples/graph.png +0 -0
- data/examples/module_graph.jpg +0 -0
- data/examples/north.rb +12 -0
- data/examples/north/Graph.log +128 -0
- data/examples/north/g.10.0.graphml +28 -0
- data/examples/north/g.10.1.graphml +28 -0
- data/examples/north/g.10.11.graphml +31 -0
- data/examples/north/g.10.12.graphml +27 -0
- data/examples/north/g.10.13.graphml +27 -0
- data/examples/north/g.10.14.graphml +27 -0
- data/examples/north/g.10.15.graphml +26 -0
- data/examples/north/g.10.16.graphml +26 -0
- data/examples/north/g.10.17.graphml +26 -0
- data/examples/north/g.10.19.graphml +37 -0
- data/examples/north/g.10.2.graphml +28 -0
- data/examples/north/g.10.20.graphml +38 -0
- data/examples/north/g.10.22.graphml +43 -0
- data/examples/north/g.10.24.graphml +30 -0
- data/examples/north/g.10.25.graphml +45 -0
- data/examples/north/g.10.27.graphml +38 -0
- data/examples/north/g.10.28.graphml +30 -0
- data/examples/north/g.10.29.graphml +38 -0
- data/examples/north/g.10.3.graphml +26 -0
- data/examples/north/g.10.30.graphml +34 -0
- data/examples/north/g.10.31.graphml +42 -0
- data/examples/north/g.10.34.graphml +42 -0
- data/examples/north/g.10.37.graphml +28 -0
- data/examples/north/g.10.38.graphml +38 -0
- data/examples/north/g.10.39.graphml +36 -0
- data/examples/north/g.10.4.graphml +26 -0
- data/examples/north/g.10.40.graphml +37 -0
- data/examples/north/g.10.41.graphml +37 -0
- data/examples/north/g.10.42.graphml +26 -0
- data/examples/north/g.10.45.graphml +28 -0
- data/examples/north/g.10.46.graphml +32 -0
- data/examples/north/g.10.5.graphml +31 -0
- data/examples/north/g.10.50.graphml +30 -0
- data/examples/north/g.10.56.graphml +29 -0
- data/examples/north/g.10.57.graphml +32 -0
- data/examples/north/g.10.58.graphml +32 -0
- data/examples/north/g.10.6.graphml +26 -0
- data/examples/north/g.10.60.graphml +32 -0
- data/examples/north/g.10.61.graphml +34 -0
- data/examples/north/g.10.62.graphml +34 -0
- data/examples/north/g.10.68.graphml +30 -0
- data/examples/north/g.10.69.graphml +32 -0
- data/examples/north/g.10.7.graphml +29 -0
- data/examples/north/g.10.70.graphml +26 -0
- data/examples/north/g.10.71.graphml +27 -0
- data/examples/north/g.10.72.graphml +28 -0
- data/examples/north/g.10.74.graphml +29 -0
- data/examples/north/g.10.75.graphml +29 -0
- data/examples/north/g.10.78.graphml +27 -0
- data/examples/north/g.10.79.graphml +34 -0
- data/examples/north/g.10.8.graphml +29 -0
- data/examples/north/g.10.80.graphml +34 -0
- data/examples/north/g.10.82.graphml +35 -0
- data/examples/north/g.10.83.graphml +32 -0
- data/examples/north/g.10.85.graphml +34 -0
- data/examples/north/g.10.86.graphml +34 -0
- data/examples/north/g.10.88.graphml +37 -0
- data/examples/north/g.10.89.graphml +29 -0
- data/examples/north/g.10.9.graphml +26 -0
- data/examples/north/g.10.90.graphml +32 -0
- data/examples/north/g.10.91.graphml +31 -0
- data/examples/north/g.10.92.graphml +26 -0
- data/examples/north/g.10.93.graphml +32 -0
- data/examples/north/g.10.94.graphml +34 -0
- data/examples/north/g.12.8.graphml +40 -0
- data/examples/north/g.14.9.graphml +36 -0
- data/examples/north2.rb +21 -0
- data/examples/rdep-rgl.rb +395 -0
- data/install.rb +49 -0
- data/lib/rgl/adjacency.rb +151 -0
- data/lib/rgl/base.rb +299 -0
- data/lib/rgl/connected_components.rb +125 -0
- data/lib/rgl/dot.rb +63 -0
- data/lib/rgl/graphxml.rb +52 -0
- data/lib/rgl/implicit.rb +151 -0
- data/lib/rgl/mutable.rb +54 -0
- data/lib/rgl/rdot.rb +264 -0
- data/lib/rgl/topsort.rb +61 -0
- data/lib/rgl/transitiv_closure.rb +34 -0
- data/lib/rgl/traversal.rb +296 -0
- data/tests/TestComponents.rb +67 -0
- data/tests/TestDirectedGraph.rb +100 -0
- data/tests/TestEdge.rb +33 -0
- data/tests/TestGraphXML.rb +57 -0
- data/tests/TestImplicit.rb +52 -0
- data/tests/TestTransitiveClosure.rb +29 -0
- data/tests/TestTraversal.rb +222 -0
- data/tests/TestUnDirectedGraph.rb +98 -0
- metadata +163 -0
data/TAGS
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
|
|
2
|
+
lib/rgl/adjacency.rb,956
|
|
3
|
+
module RGLRGL16,586
|
|
4
|
+
class DirectedAdjacencyGraphDirectedAdjacencyGraph17,597
|
|
5
|
+
def initialize(edgelist_class=Set)initialize33,1091
|
|
6
|
+
def each_vertex(&b)each_vertex39,1248
|
|
7
|
+
def each_adjacent(v, &b) # :nodoc:each_adjacent43,1305
|
|
8
|
+
def directed?; true; enddirected?49,1470
|
|
9
|
+
def has_vertex?(v); @vertice_dict.has_key?(v); endhas_vertex?53,1619
|
|
10
|
+
def has_edge? (u, v)has_edge?60,1799
|
|
11
|
+
def add_vertex(v)add_vertex67,1981
|
|
12
|
+
def add_edge (u,v)add_edge72,2080
|
|
13
|
+
def remove_vertex(v)remove_vertex79,2230
|
|
14
|
+
def remove_edge (u,v)remove_edge87,2422
|
|
15
|
+
def basic_add_edge(u,v)basic_add_edge93,2522
|
|
16
|
+
class AdjacencyGraph < DirectedAdjacencyGraphAdjacencyGraph101,2812
|
|
17
|
+
def directed?; false; enddirected?103,2885
|
|
18
|
+
def remove_edge (u,v)remove_edge106,2936
|
|
19
|
+
def basic_add_edge(u,v)basic_add_edge112,3044
|
|
20
|
+
module GraphGraph119,3143
|
|
21
|
+
def to_adjacencyto_adjacency122,3291
|
|
22
|
+
def reversereverse132,3639
|
|
23
|
+
def to_undirectedto_undirected144,4009
|
|
24
|
+
|
|
25
|
+
lib/rgl/base.rb,1907
|
|
26
|
+
module EnumerableEnumerable12,301
|
|
27
|
+
def inject(*argv)inject13,321
|
|
28
|
+
module EnumerableEnumerable41,700
|
|
29
|
+
def lengthlength48,892
|
|
30
|
+
module RGLRGL55,954
|
|
31
|
+
class NotDirectedError < RuntimeError; endNotDirectedError56,965
|
|
32
|
+
class NotUndirectedError < RuntimeError; endNotUndirectedError57,1010
|
|
33
|
+
class NoVertexError < IndexError; endNoVertexError59,1058
|
|
34
|
+
class NoEdgeError < IndexError; endNoEdgeError60,1098
|
|
35
|
+
module EdgeEdge65,1327
|
|
36
|
+
class DirectedEdgeDirectedEdge71,1651
|
|
37
|
+
def initialize (a,b)initialize80,1874
|
|
38
|
+
def eql?(edge)eql?86,2086
|
|
39
|
+
def reversereverse92,2216
|
|
40
|
+
def to_sto_s101,2504
|
|
41
|
+
def to_a; [source,target]; endto_a105,2589
|
|
42
|
+
class UnDirectedEdge < DirectedEdgeUnDirectedEdge115,2894
|
|
43
|
+
def eql?(edge)eql?116,2931
|
|
44
|
+
def hashhash120,3021
|
|
45
|
+
def to_s; "(#{source}=#{target})"; endto_s125,3113
|
|
46
|
+
module GraphGraph144,3938
|
|
47
|
+
def each_vertexeach_vertex151,4151
|
|
48
|
+
def each_adjacent (v)each_adjacent159,4401
|
|
49
|
+
def each_edge (&block)each_edge171,4882
|
|
50
|
+
def each(&block); each_vertex(&block); endeach184,5165
|
|
51
|
+
def directed?; false; enddirected?187,5264
|
|
52
|
+
def has_vertex?(v); include?(v); end # inherited from enumerablehas_vertex?192,5490
|
|
53
|
+
def empty?; num_vertices.zero?; endempty?197,5668
|
|
54
|
+
def vertices; to_a; endvertices200,5781
|
|
55
|
+
def edge_class; directed? ? DirectedEdge : UnDirectedEdge; endedge_class203,5871
|
|
56
|
+
def edgesedges207,6079
|
|
57
|
+
def adjacent_vertices (v)adjacent_vertices215,6239
|
|
58
|
+
def out_degree (v)out_degree223,6451
|
|
59
|
+
def size # Why not in Enumerable?size230,6560
|
|
60
|
+
def num_vertices; size; endnum_vertices236,6732
|
|
61
|
+
def num_edges; r = 0; each_edge {|u,v| r +=1}; r; endnum_edges239,6794
|
|
62
|
+
def to_sto_s242,6927
|
|
63
|
+
def each_edge_auxeach_edge_aux248,6973
|
|
64
|
+
module BidirectionalGraphBidirectionalGraph272,7816
|
|
65
|
+
def each_in_neighbor (v)each_in_neighbor279,8156
|
|
66
|
+
def in_degree (v)in_degree286,8359
|
|
67
|
+
def degree (v)degree294,8582
|
|
68
|
+
|
|
69
|
+
lib/rgl/connected_components.rb,497
|
|
70
|
+
module RGLRGL7,233
|
|
71
|
+
module GraphGraph8,244
|
|
72
|
+
def each_connected_componenteach_connected_component17,641
|
|
73
|
+
class TarjanSccVisitor < DFSVisitorTarjanSccVisitor34,1174
|
|
74
|
+
def initialize(g)initialize38,1314
|
|
75
|
+
def handle_examine_vertex(v)handle_examine_vertex48,1458
|
|
76
|
+
def handle_finish_vertex(v)handle_finish_vertex56,1606
|
|
77
|
+
def num_compnum_comp75,2151
|
|
78
|
+
def min_discover_time(u,v)min_discover_time81,2198
|
|
79
|
+
def strongly_connected_componentsstrongly_connected_components118,3687
|
|
80
|
+
|
|
81
|
+
lib/rgl/dot.rb,298
|
|
82
|
+
module RGLRGL10,239
|
|
83
|
+
module GraphGraph11,250
|
|
84
|
+
def to_dot_graph( params = {} )to_dot_graph15,428
|
|
85
|
+
def print_dotted_on (params = {}, s=$stdout)print_dotted_on35,1076
|
|
86
|
+
def dotty( params = {} )dotty41,1270
|
|
87
|
+
def write_to_graphic_file(fmt='png', dotfile="graph")write_to_graphic_file51,1530
|
|
88
|
+
|
|
89
|
+
lib/rgl/graphxml.rb,340
|
|
90
|
+
module RGLRGL15,594
|
|
91
|
+
module GraphXMLGraphXML22,893
|
|
92
|
+
class MutableGraphParserMutableGraphParser23,911
|
|
93
|
+
def initialize(graph)initialize26,992
|
|
94
|
+
def tag_start(name, attrs)tag_start30,1042
|
|
95
|
+
def MutableGraph.append_features(includingClass)append_features41,1229
|
|
96
|
+
def includingClass.from_graphxml (source)from_graphxml45,1350
|
|
97
|
+
|
|
98
|
+
lib/rgl/implicit.rb,681
|
|
99
|
+
module RGLRGL19,702
|
|
100
|
+
class ImplicitGraphImplicitGraph20,713
|
|
101
|
+
def initializeinitialize32,1102
|
|
102
|
+
def directed?; @directed; enddirected?40,1337
|
|
103
|
+
def each_vertex (&block) # :nodoc:each_vertex42,1370
|
|
104
|
+
def each_adjacent (v, &block) # :nodoc:each_adjacent46,1444
|
|
105
|
+
def each_edge (&block) # :nodoc:each_edge50,1527
|
|
106
|
+
def vertex_iterator (&block)vertex_iterator60,1811
|
|
107
|
+
def adjacent_iterator (&block)adjacent_iterator69,2127
|
|
108
|
+
def edge_iterator (&block)edge_iterator76,2367
|
|
109
|
+
module GraphGraph81,2433
|
|
110
|
+
def vertices_filtered_by (&filter)vertices_filtered_by105,3129
|
|
111
|
+
def edges_filtered_by (&filter)edges_filtered_by124,3675
|
|
112
|
+
def implicit_graphimplicit_graph141,4120
|
|
113
|
+
|
|
114
|
+
lib/rgl/mutable.rb,484
|
|
115
|
+
module RGLRGL3,20
|
|
116
|
+
module MutableGraphMutableGraph6,121
|
|
117
|
+
def add_vertex(v); raise NotImplementedError; endadd_vertex11,266
|
|
118
|
+
def add_edge(u, v); raise NotImplementedError; endadd_edge20,692
|
|
119
|
+
def add_vertices (*a)add_vertices23,790
|
|
120
|
+
def add_edges (*edges)add_edges30,1010
|
|
121
|
+
def remove_vertex(v); raise NotImplementedError; endremove_vertex39,1365
|
|
122
|
+
def remove_edge(u, v); raise NotImplementedError; endremove_edge46,1653
|
|
123
|
+
def remove_vertices (*a)remove_vertices50,1798
|
|
124
|
+
|
|
125
|
+
lib/rgl/rdot.rb,1615
|
|
126
|
+
module DOTDOT9,242
|
|
127
|
+
def change_tab( t )change_tab16,420
|
|
128
|
+
class DOTSimpleElementDOTSimpleElement81,1613
|
|
129
|
+
def initialize( params = {} )initialize84,1669
|
|
130
|
+
def to_sto_s88,1778
|
|
131
|
+
class DOTElement < DOTSimpleElementDOTElement94,1897
|
|
132
|
+
def initialize( params = {}, option_list = [] )initialize98,2005
|
|
133
|
+
def each_optioneach_option109,2419
|
|
134
|
+
def each_option_paireach_option_pair113,2497
|
|
135
|
+
class DOTPort < DOTSimpleElementDOTPort126,2856
|
|
136
|
+
def initialize( params = {} )initialize129,2931
|
|
137
|
+
def to_sto_s133,3068
|
|
138
|
+
class DOTNode < DOTElementDOTNode139,3200
|
|
139
|
+
def initialize( params = {}, option_list = NODE_OPTS )initialize142,3247
|
|
140
|
+
def each_porteach_port147,3424
|
|
141
|
+
def push ( thing )push155,3564
|
|
142
|
+
def poppop159,3637
|
|
143
|
+
def to_s( t = '' )to_s163,3689
|
|
144
|
+
class DOTSubgraph < DOTElementDOTSubgraph188,4604
|
|
145
|
+
def initialize( params = {}, option_list = GRAPH_OPTS )initialize192,4675
|
|
146
|
+
def each_nodeeach_node198,4887
|
|
147
|
+
def push( thing )push206,5034
|
|
148
|
+
def poppop210,5106
|
|
149
|
+
def to_s( t = '' )to_s214,5158
|
|
150
|
+
class DOTDigraph < DOTSubgraphDOTDigraph231,5663
|
|
151
|
+
def initialize( params = {}, option_list = GRAPH_OPTS )initialize232,5698
|
|
152
|
+
class DOTEdge < DOTElementDOTEdge239,5879
|
|
153
|
+
def initialize( params = {}, option_list = EDGE_OPTS )initialize241,5943
|
|
154
|
+
def edge_link; '--'; endedge_link247,6177
|
|
155
|
+
def to_s( t = '' )to_s248,6204
|
|
156
|
+
class DOTDirectedEdge < DOTEdgeDOTDirectedEdge258,6557
|
|
157
|
+
def edge_link; '->'; endedge_link259,6590
|
|
158
|
+
|
|
159
|
+
lib/rgl/topsort.rb,447
|
|
160
|
+
module RGLRGL3,25
|
|
161
|
+
class TopsortIteratorTopsortIterator14,503
|
|
162
|
+
def initialize(g)initialize16,550
|
|
163
|
+
def set_to_begin # :nodoc:set_to_begin21,602
|
|
164
|
+
def basic_forward # :nodoc:basic_forward36,924
|
|
165
|
+
def at_beginning?; true; end # :nodoc: FIXMEat_beginning?45,1091
|
|
166
|
+
def at_end?; @waiting.empty?; end # :nodoc:at_end?46,1138
|
|
167
|
+
module GraphGraph49,1190
|
|
168
|
+
def topsort_iteratortopsort_iterator51,1235
|
|
169
|
+
def acyclic?acyclic?57,1425
|
|
170
|
+
|
|
171
|
+
lib/rgl/transitiv_closure.rb,127
|
|
172
|
+
module RGLRGL9,334
|
|
173
|
+
module GraphGraph10,345
|
|
174
|
+
def transitive_closure_floyd_warshaltransitive_closure_floyd_warshal16,665
|
|
175
|
+
|
|
176
|
+
lib/rgl/traversal.rb,1708
|
|
177
|
+
module RGLRGL14,546
|
|
178
|
+
module GraphWrapper # :nodoc:GraphWrapper15,557
|
|
179
|
+
def initialize(graph); @graph = graph; endinitialize19,658
|
|
180
|
+
module GraphIteratorGraphIterator24,863
|
|
181
|
+
module GraphVisitorGraphVisitor59,2225
|
|
182
|
+
def initialize(graph)initialize64,2335
|
|
183
|
+
def resetreset70,2432
|
|
184
|
+
def finished_vertex? vfinished_vertex?75,2546
|
|
185
|
+
def attach_distance_map(map=Hash.new(0))attach_distance_map87,2937
|
|
186
|
+
def handle_tree_edge(u,v)handle_tree_edge90,3015
|
|
187
|
+
def distance_to_root(v)distance_to_root96,3141
|
|
188
|
+
def follow_edge?(u,v) # :nodoc:follow_edge?103,3261
|
|
189
|
+
def self.def_event_handler(m)def_event_handler108,3355
|
|
190
|
+
def handle_#{m}(#{params})handle_111,3446
|
|
191
|
+
def set_#{m}_event_handler(&b)set_114,3553
|
|
192
|
+
class BFSIteratorBFSIterator137,4373
|
|
193
|
+
def initialize(graph, start=graph.detect{|x| true})initialize143,4535
|
|
194
|
+
def at_beginning?; @color_map.size == 1; end # :nodoc:at_beginning?150,4727
|
|
195
|
+
def at_end?; @waiting.empty?; endat_end?153,4823
|
|
196
|
+
def set_to_beginset_to_begin156,4932
|
|
197
|
+
def basic_forward # :nodoc:basic_forward162,5098
|
|
198
|
+
def next_vertex () # :nodoc:next_vertex186,5696
|
|
199
|
+
module GraphGraph192,5804
|
|
200
|
+
def bfs_iterator (v=self.detect {|x| true})bfs_iterator194,5867
|
|
201
|
+
def bfs_search_tree_from(v)bfs_search_tree_from201,6151
|
|
202
|
+
class DFSIterator < BFSIteratorDFSIterator218,6699
|
|
203
|
+
def next_vertexnext_vertex219,6733
|
|
204
|
+
class DFSVisitorDFSVisitor235,7372
|
|
205
|
+
module GraphGraph241,7469
|
|
206
|
+
def dfs_iterator (v=self.detect {|x| true})dfs_iterator243,7532
|
|
207
|
+
def depth_first_search (vis = DFSVisitor.new(self),&b)depth_first_search250,7787
|
|
208
|
+
def depth_first_visit (u, vis = DFSVisitor.new(self), &b)depth_first_visit261,8079
|
|
209
|
+
def acyclic?acyclic?285,8775
|
data/examples/canvas.rb
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# From c.l.r SNIP IT: bond TkCanvas with RubyGraphLibrary
|
|
2
|
+
# author: Phlip (see also
|
|
3
|
+
# http://www.rubygarden.org/ruby?RubyAlgorithmPackage/TkCanvasSample)
|
|
4
|
+
#
|
|
5
|
+
# put a GraphViz graph into a TkCanvas, and make nodes
|
|
6
|
+
# selectable. Illustrates a bug in GraphViz
|
|
7
|
+
|
|
8
|
+
require 'rgl/graphxml'
|
|
9
|
+
require 'rgl/adjacency'
|
|
10
|
+
require 'rgl/dot'
|
|
11
|
+
require 'tk'
|
|
12
|
+
|
|
13
|
+
include RGL
|
|
14
|
+
filename = ARGV[0]
|
|
15
|
+
puts 'Displaying ' + filename
|
|
16
|
+
|
|
17
|
+
# ruby canvas.rb north/g.10.8.graphml &
|
|
18
|
+
# ruby canvas.rb north/g.12.8.graphml &
|
|
19
|
+
# ruby canvas.rb north/g.14.9.graphml &
|
|
20
|
+
|
|
21
|
+
File.open(filename) { |file|
|
|
22
|
+
graph = DirectedAdjacencyGraph.from_graphxml(file)
|
|
23
|
+
graph.write_to_graphic_file('gif', filename)
|
|
24
|
+
graph.write_to_graphic_file('plain', filename)
|
|
25
|
+
root = TkRoot.new{title "Ex1"}
|
|
26
|
+
|
|
27
|
+
canvas = TkCanvas.new(root) {
|
|
28
|
+
width 400
|
|
29
|
+
height 600
|
|
30
|
+
}
|
|
31
|
+
canvas.pack()
|
|
32
|
+
ovals = []
|
|
33
|
+
|
|
34
|
+
TkcImage.new(canvas, 0, 0) {
|
|
35
|
+
anchor 'nw'
|
|
36
|
+
|
|
37
|
+
image TkPhotoImage.new() {
|
|
38
|
+
file filename + '.gif'
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
# read the 'plain' file, and for each node put an invisible
|
|
43
|
+
# oval over its image
|
|
44
|
+
|
|
45
|
+
File.open(filename + '.plain') { |f|
|
|
46
|
+
graphLine = f.readline()
|
|
47
|
+
graphStats = graphLine.split()
|
|
48
|
+
graphHeight = graphStats[3].to_f()
|
|
49
|
+
nodeLine = f.readline()
|
|
50
|
+
fields = nodeLine.split()
|
|
51
|
+
|
|
52
|
+
while fields[0] == 'node'
|
|
53
|
+
namer = fields[1]
|
|
54
|
+
|
|
55
|
+
# the following crud is because GraphViz has no system to
|
|
56
|
+
# emit a "plain" format in pixels that exactly match the
|
|
57
|
+
# locations of objects in dot's raster output
|
|
58
|
+
|
|
59
|
+
# furtherless, the current GraphViz seems to be centering
|
|
60
|
+
# the raster output but not the 'plain' output. Hence on
|
|
61
|
+
# g.10.8.graphml the X fudge factor must be 45. >sigh<
|
|
62
|
+
|
|
63
|
+
# YMMV, based on your system's opinion of the size of an inch
|
|
64
|
+
|
|
65
|
+
exx = fields[2].to_f * 96 - 20 # 45
|
|
66
|
+
why = (graphHeight - fields[3].to_f()) * 96 - 20
|
|
67
|
+
widt = fields[4].to_f() * 90
|
|
68
|
+
hite = fields[5].to_f() * 90
|
|
69
|
+
|
|
70
|
+
ov = TkcOval.new(canvas, exx, why,
|
|
71
|
+
exx + widt, why + hite) {
|
|
72
|
+
state 'hidden'
|
|
73
|
+
width 4
|
|
74
|
+
outline 'green'
|
|
75
|
+
tags namer
|
|
76
|
+
}
|
|
77
|
+
ovals.push(ov)
|
|
78
|
+
nodeLine = f.readline()
|
|
79
|
+
fields = nodeLine.split()
|
|
80
|
+
end
|
|
81
|
+
}
|
|
82
|
+
lastOval = ovals[0]
|
|
83
|
+
|
|
84
|
+
# at click time, search for an oval in range and display it
|
|
85
|
+
|
|
86
|
+
canvas.bind('Button-1') do |event|
|
|
87
|
+
x,y = canvas.canvasx(event.x), canvas.canvasy(event.y)
|
|
88
|
+
|
|
89
|
+
ovals.each { |r|
|
|
90
|
+
x1,y1,x2,y2 = r.coords()
|
|
91
|
+
|
|
92
|
+
if x >= x1 and x <= x2 and y >= y1 and y <= y2 then
|
|
93
|
+
lastOval.configure('state' => 'hidden')
|
|
94
|
+
lastOval = r
|
|
95
|
+
lastOval.configure('state' => 'normal')
|
|
96
|
+
break
|
|
97
|
+
end
|
|
98
|
+
}
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
Tk.mainloop
|
|
102
|
+
}
|
|
103
|
+
|
data/examples/codegraph
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
require 'ptools'
|
|
3
|
+
require 'rgl/adjacency'
|
|
4
|
+
require 'rgl/dot'
|
|
5
|
+
require 'rgl/rdot'
|
|
6
|
+
|
|
7
|
+
class FunctionGraph < RGL::DirectedAdjacencyGraph
|
|
8
|
+
attr_accessor :command
|
|
9
|
+
attr_accessor :funx
|
|
10
|
+
attr_accessor :lines
|
|
11
|
+
def initialize
|
|
12
|
+
super
|
|
13
|
+
@@lines = nil
|
|
14
|
+
@@funx = nil
|
|
15
|
+
end
|
|
16
|
+
def genFiles(graph, filelist, lang, exclude=[])
|
|
17
|
+
# test if the 'tobegenerated' files already exist
|
|
18
|
+
if (File.exist?('all.php') or File.exist?('php-funx'))
|
|
19
|
+
puts "Die Dateien 'all.php' oder 'php-funx' exitieren bereits."
|
|
20
|
+
puts "Bitte loeschen Sie sie manuel"
|
|
21
|
+
exit
|
|
22
|
+
end
|
|
23
|
+
# command to generate the necessary files
|
|
24
|
+
command = 'cat ' + filelist + ' | ruby -ne \' print unless /^#.*$/\' |
|
|
25
|
+
ruby -pe \'gsub(/#.*/," "); gsub(/".*"/,"")\' > all.php;
|
|
26
|
+
ctags -x --php-kinds=f all.php | sort -n -k 3 |
|
|
27
|
+
ruby -pe \'gsub(/ function /,"\t"); gsub(/all.php/,"\t")\' |
|
|
28
|
+
cut -f 1,2 |ruby -pe \'gsub(/ {2,}/,"")\' > php-funx'
|
|
29
|
+
system(command)
|
|
30
|
+
funchash = Hash.new
|
|
31
|
+
file = open('php-funx')
|
|
32
|
+
file.read.split(/\n/).each {|f|
|
|
33
|
+
thisfunc = f.split
|
|
34
|
+
funchash.store(thisfunc.last.to_i, thisfunc.first)
|
|
35
|
+
}
|
|
36
|
+
graph.lines = Array.new
|
|
37
|
+
graph.funx = Array.new
|
|
38
|
+
funchash.sort.each {|f|
|
|
39
|
+
next if exclude.include?(f.last)
|
|
40
|
+
graph.lines << f.first
|
|
41
|
+
graph.funx << f.last
|
|
42
|
+
}
|
|
43
|
+
$filesize = open('all.php').readlines.size
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def fill(filelist,lang,exclude=[])
|
|
47
|
+
# generate the necessary files and return the size (in number of lines)
|
|
48
|
+
# of the file with all definitions
|
|
49
|
+
genFiles(self,filelist,lang,exclude)
|
|
50
|
+
# scan the first function
|
|
51
|
+
funcbody = File.middle('all.php', lines[0]+1, lines[1]-1).to_s
|
|
52
|
+
add_vertex(funx.first)
|
|
53
|
+
funx.each {|func|
|
|
54
|
+
if funcbody =~ /#{func} *\(/
|
|
55
|
+
add_func("#{funx.first}","#{func}")
|
|
56
|
+
end
|
|
57
|
+
}
|
|
58
|
+
# scan any other function except the last
|
|
59
|
+
(1...funx.size-1).each {|index|
|
|
60
|
+
add_vertex(funx[index])
|
|
61
|
+
funcbody = File.middle('all.php', lines[index]+1,lines[index+1]-1).to_s
|
|
62
|
+
funx.each {|func|
|
|
63
|
+
if funcbody =~ /#{func} *\(/
|
|
64
|
+
add_func("#{funx[index]}","#{func}")
|
|
65
|
+
end
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
# scan the last function
|
|
69
|
+
funcbody = File.middle('all.php', lines.last+1 , $filesize).to_s
|
|
70
|
+
add_vertex(funx.last)
|
|
71
|
+
funx.each {|func|
|
|
72
|
+
if funcbody =~ /#{func} *\(/
|
|
73
|
+
add_func("#{funx.last}","#{func}")
|
|
74
|
+
end
|
|
75
|
+
}
|
|
76
|
+
system('rm all.php php-funx')
|
|
77
|
+
|
|
78
|
+
# add fallow function's knodes
|
|
79
|
+
funx.each {|func|
|
|
80
|
+
if not has_vertex?(func)
|
|
81
|
+
add_edge("UNUSED CODE",func)
|
|
82
|
+
end
|
|
83
|
+
}
|
|
84
|
+
end
|
|
85
|
+
def to_ps(filename)
|
|
86
|
+
if File.exist?(filename)
|
|
87
|
+
system("rm #{filename}")
|
|
88
|
+
end
|
|
89
|
+
if File.exist?(filename+".dot")
|
|
90
|
+
system("rm #{filename}.dot")
|
|
91
|
+
end
|
|
92
|
+
# create dot file
|
|
93
|
+
params = Hash['rankdir' => 'LR',
|
|
94
|
+
'ranksep' => '2.0',
|
|
95
|
+
'concentrate' => 'TRUE',
|
|
96
|
+
'fontsize' => '10']
|
|
97
|
+
File.open("#{filename}.dot","w") {|f|
|
|
98
|
+
print_dotted_on(params,f)
|
|
99
|
+
}
|
|
100
|
+
system("dot -Tps -o #{filename} -Nshape=box #{filename}.dot")
|
|
101
|
+
end
|
|
102
|
+
def add_func(f,g)
|
|
103
|
+
add_edge(f,g)
|
|
104
|
+
end
|
|
105
|
+
def display
|
|
106
|
+
params = Hash['rankdir' => 'LR',
|
|
107
|
+
'ranksep' => '2.0',
|
|
108
|
+
'concentrate' => 'TRUE',
|
|
109
|
+
'label' => 'LCWA',
|
|
110
|
+
'fontsize' => '12']
|
|
111
|
+
dotty(params)
|
|
112
|
+
end
|
|
113
|
+
private :genFiles
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
class SingleFunctionGraph < FunctionGraph
|
|
117
|
+
attr_accessor :func
|
|
118
|
+
def initialize(func)
|
|
119
|
+
@func = func
|
|
120
|
+
super()
|
|
121
|
+
end
|
|
122
|
+
def fill(filelist,lang,exclude=[])
|
|
123
|
+
genFiles(self,filelist,lang,exclude)
|
|
124
|
+
$scannedfunx = Array.new
|
|
125
|
+
scan(self, func)
|
|
126
|
+
system('rm all.php php-funx')
|
|
127
|
+
end
|
|
128
|
+
def scan(graph, f)
|
|
129
|
+
if ($scannedfunx.include?(f))
|
|
130
|
+
else
|
|
131
|
+
$scannedfunx << f
|
|
132
|
+
beginbody = graph.lines[graph.funx.index(f)]+1
|
|
133
|
+
if (graph.lines.size <= graph.funx.index(f)+1)
|
|
134
|
+
endbody = $filesize
|
|
135
|
+
else
|
|
136
|
+
endbody = graph.lines[graph.funx.index(f)+1]-1
|
|
137
|
+
end
|
|
138
|
+
fbody = File.middle('all.php', beginbody, endbody).to_s
|
|
139
|
+
graph.funx.each {|g|
|
|
140
|
+
if fbody =~ /#{g} *\(/
|
|
141
|
+
graph.add_func(f,g)
|
|
142
|
+
scan(graph,g)
|
|
143
|
+
end
|
|
144
|
+
}
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
private :scan
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# main script #################################################################
|
|
151
|
+
require 'getoptlong'
|
|
152
|
+
|
|
153
|
+
def show_usage
|
|
154
|
+
puts <<-END
|
|
155
|
+
Usage: #{__FILE__}: --help guess what
|
|
156
|
+
|
|
157
|
+
--source, -s take every $IMPSRC/lcwa/web_interface/*inc.php file
|
|
158
|
+
to search in
|
|
159
|
+
--local, -l take every $(pwd)/*.inc.php file for scanning
|
|
160
|
+
|
|
161
|
+
--file-list, -F "<list>"
|
|
162
|
+
fill the graph with every function,
|
|
163
|
+
that has a definiton inside the given files
|
|
164
|
+
|
|
165
|
+
--function, -f <funcname>
|
|
166
|
+
take the given func as the root knode
|
|
167
|
+
--exclude, -x "<list>"
|
|
168
|
+
exclude a list of functions from the graph
|
|
169
|
+
--to-ps, -p <filename>
|
|
170
|
+
create a postscript file from the graph
|
|
171
|
+
END
|
|
172
|
+
end
|
|
173
|
+
# option setting ---------------------------------------------------------------
|
|
174
|
+
options = GetoptLong.new(
|
|
175
|
+
['--help', '-h', GetoptLong::NO_ARGUMENT],
|
|
176
|
+
['--local', '-l', GetoptLong::NO_ARGUMENT],
|
|
177
|
+
['--source', '-s', GetoptLong::NO_ARGUMENT],
|
|
178
|
+
['--function', '-f', GetoptLong::REQUIRED_ARGUMENT],
|
|
179
|
+
['--file-list', '-F', GetoptLong::REQUIRED_ARGUMENT],
|
|
180
|
+
['--to-ps', '-p', GetoptLong::REQUIRED_ARGUMENT],
|
|
181
|
+
['--exclude', '-x', GetoptLong::REQUIRED_ARGUMENT]
|
|
182
|
+
)
|
|
183
|
+
options.ordering = GetoptLong::RETURN_IN_ORDER
|
|
184
|
+
# the default options ----------------------------------------------------------
|
|
185
|
+
filelist = ''
|
|
186
|
+
mode = 'multiple'
|
|
187
|
+
createPS = false
|
|
188
|
+
filename = ''
|
|
189
|
+
function = ''
|
|
190
|
+
exclude = Array.new
|
|
191
|
+
spaces = Array.new
|
|
192
|
+
# option parsing ---------------------------------------------------------------
|
|
193
|
+
options.each do |opt, arg|
|
|
194
|
+
case opt
|
|
195
|
+
when '--local'
|
|
196
|
+
filelist = './*inc.php'
|
|
197
|
+
spaces << filelist
|
|
198
|
+
when '--source'
|
|
199
|
+
filelist = '$IMPSRC/lcwa/web_interface/*inc.php'
|
|
200
|
+
spaces << filelist
|
|
201
|
+
when '--file-list'
|
|
202
|
+
filelist = arg
|
|
203
|
+
spaces << filelist
|
|
204
|
+
when '--function'
|
|
205
|
+
mode = 'single'
|
|
206
|
+
function = arg
|
|
207
|
+
when '--to-ps'
|
|
208
|
+
createPS = true
|
|
209
|
+
filename = arg
|
|
210
|
+
when '--exclude'
|
|
211
|
+
exclude = arg.split(/ /)
|
|
212
|
+
else
|
|
213
|
+
show_usage
|
|
214
|
+
exit
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
options.terminate
|
|
218
|
+
# script controlling ###########################################################
|
|
219
|
+
case mode
|
|
220
|
+
when 'single'
|
|
221
|
+
g = SingleFunctionGraph.new(function)
|
|
222
|
+
else
|
|
223
|
+
g = FunctionGraph.new
|
|
224
|
+
end
|
|
225
|
+
case spaces.size
|
|
226
|
+
when 1
|
|
227
|
+
g.fill(filelist,'php',exclude)
|
|
228
|
+
else
|
|
229
|
+
puts "Benutzen Sie entweder --local, --source oder --file-list <list>"
|
|
230
|
+
show_usage
|
|
231
|
+
exit
|
|
232
|
+
end
|
|
233
|
+
case createPS
|
|
234
|
+
when true
|
|
235
|
+
g.to_ps(filename)
|
|
236
|
+
else
|
|
237
|
+
g.display
|
|
238
|
+
end
|