rgl 0.6.2 → 0.6.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +37 -2
- data/examples/graph.dot +18 -934
- data/lib/rgl/base.rb +1 -1
- data/lib/rgl/dot.rb +46 -14
- data/lib/rgl/rdot.rb +185 -134
- data/test/dot_test.rb +23 -29
- metadata +2 -2
data/lib/rgl/base.rb
CHANGED
data/lib/rgl/dot.rb
CHANGED
@@ -10,9 +10,7 @@
|
|
10
10
|
require 'rgl/rdot'
|
11
11
|
|
12
12
|
module RGL
|
13
|
-
|
14
13
|
module Graph
|
15
|
-
|
16
14
|
# Returns a label for vertex v. Default is v.to_s
|
17
15
|
def vertex_label(v)
|
18
16
|
v.to_s
|
@@ -22,6 +20,27 @@ module RGL
|
|
22
20
|
v
|
23
21
|
end
|
24
22
|
|
23
|
+
# Set the configuration values for the given vertex
|
24
|
+
def set_vertex_options(vertex, **options)
|
25
|
+
@vertex_options ||= {}
|
26
|
+
@vertex_options[vertex] ||= {}
|
27
|
+
|
28
|
+
RGL::DOT::NODE_OPTS.each do |opt|
|
29
|
+
@vertex_options[vertex][:"#{opt}"] = options[:"#{opt}"] if options.key?(:"#{opt}")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Set the configuration values for the given edge
|
34
|
+
def set_edge_options(u, v, **options)
|
35
|
+
edge = edge_class.new(u, v)
|
36
|
+
@edge_options ||= {}
|
37
|
+
@edge_options[edge] ||= {}
|
38
|
+
|
39
|
+
RGL::DOT::EDGE_OPTS.each do |opt|
|
40
|
+
@edge_options[edge][:"#{opt}"] = options[:"#{opt}"] if options.key?(:"#{opt}")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
25
44
|
# Return a {DOT::Digraph} for directed graphs or a {DOT::Graph} for an
|
26
45
|
# undirected {Graph}. _params_ can contain any graph property specified in
|
27
46
|
# rdot.rb.
|
@@ -31,30 +50,43 @@ module RGL
|
|
31
50
|
fontsize = params['fontsize'] ? params['fontsize'] : '8'
|
32
51
|
graph = (directed? ? DOT::Digraph : DOT::Graph).new(params)
|
33
52
|
edge_class = directed? ? DOT::DirectedEdge : DOT::Edge
|
34
|
-
vertex_options = params['vertex'] || {}
|
35
|
-
edge_options = params['edge'] || {}
|
36
53
|
|
37
54
|
each_vertex do |v|
|
38
|
-
default_vertex_options =
|
55
|
+
default_vertex_options = {
|
39
56
|
'name' => vertex_id(v),
|
40
57
|
'fontsize' => fontsize,
|
41
58
|
'label' => vertex_label(v)
|
42
59
|
}
|
43
|
-
each_vertex_options = default_vertex_options
|
44
|
-
|
60
|
+
each_vertex_options = default_vertex_options
|
61
|
+
|
62
|
+
if @vertex_options && @vertex_options[v]
|
63
|
+
RGL::DOT::NODE_OPTS.each do |opt|
|
64
|
+
if @vertex_options[v].key?(:"#{opt}")
|
65
|
+
each_vertex_options["#{opt}"] = @vertex_options[v].fetch(:"#{opt}")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
45
69
|
graph << DOT::Node.new(each_vertex_options)
|
46
70
|
end
|
47
71
|
|
48
|
-
|
72
|
+
edges.each do |edge|
|
49
73
|
default_edge_options = {
|
50
|
-
'from' =>
|
51
|
-
'to' =>
|
74
|
+
'from' => edge.source,
|
75
|
+
'to' => edge.target,
|
52
76
|
'fontsize' => fontsize
|
53
77
|
}
|
54
|
-
|
55
|
-
|
78
|
+
|
79
|
+
each_edge_options = default_edge_options
|
80
|
+
|
81
|
+
if @edge_options && @edge_options[edge]
|
82
|
+
RGL::DOT::EDGE_OPTS.each do |opt|
|
83
|
+
if @edge_options[edge].key?(:"#{opt}")
|
84
|
+
each_edge_options["#{opt}"] = @edge_options[edge].fetch(:"#{opt}")
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
56
88
|
graph << edge_class.new(each_edge_options)
|
57
|
-
|
89
|
+
end
|
58
90
|
|
59
91
|
graph
|
60
92
|
end
|
@@ -81,7 +113,7 @@ module RGL
|
|
81
113
|
# Use dot[https://www.graphviz.org] to create a graphical representation of
|
82
114
|
# the graph. Returns the filename of the graphics file.
|
83
115
|
#
|
84
|
-
def write_to_graphic_file(fmt='png', dotfile="graph", options={})
|
116
|
+
def write_to_graphic_file(fmt = 'png', dotfile = "graph", options = {})
|
85
117
|
src = dotfile + ".dot"
|
86
118
|
dot = dotfile + "." + fmt
|
87
119
|
|
data/lib/rgl/rdot.rb
CHANGED
@@ -7,131 +7,185 @@ module RGL
|
|
7
7
|
# It also supports undirected edges.
|
8
8
|
module DOT
|
9
9
|
|
10
|
-
#
|
10
|
+
# attributes due to
|
11
|
+
# https://www.graphviz.org/pdf/dotguide.pdf
|
12
|
+
# January 5, 2015
|
11
13
|
|
14
|
+
# options for node declaration
|
12
15
|
NODE_OPTS = [
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
16
|
+
'color', # default: black; node shape color
|
17
|
+
'colorscheme', # default: X11; scheme for interpreting color names
|
18
|
+
'comment', # any string (format-dependent)
|
19
|
+
'distortion', # default: 0.0; node distortion for shape=polygon
|
20
|
+
'fillcolor', # default: lightgrey/black; node fill color
|
21
|
+
'fixedsize', # default: false; label text has no affect on node size
|
22
|
+
'fontcolor', # default: black; type face color
|
23
|
+
'fontname', # default: Times-Roman; font family
|
24
|
+
'fontsize', # default: 14; point size of label
|
25
|
+
'group', # name of node's group
|
26
|
+
'height', # default: .5; height in inches
|
27
|
+
'id', # any string (user-defined output object tags)
|
28
|
+
'label', # default: node name; any string
|
29
|
+
'labelloc', # default: c; node label vertical alignment
|
30
|
+
'layer', # default: overlay range; all, id or id:id
|
31
|
+
'margin', # default: 0.11,0.55; space around label
|
32
|
+
'nojustify', # default: false; if true, justify to label, not node
|
33
|
+
'orientation', # default: 0.0; node rotation angle
|
34
|
+
'penwidth', # default: 1.0; width of pen for drawing boundaries, in points
|
35
|
+
'peripheries', # shape-dependent number of node boundaries
|
36
|
+
'regular', # default: false; force polygon to be regular
|
37
|
+
'samplepoints', # default 8 or 20; number vertices to convert circle or ellipse
|
38
|
+
'shape', # default: ellipse; node shape; see Section 2.1 and Appendix E
|
39
|
+
'shapefile', # external EPSF or SVG custom shape file
|
40
|
+
'sides', # default: 4; number of sides for shape=polygon
|
41
|
+
'skew', # default: 0.0; skewing of node for shape=polygon
|
42
|
+
'style', # graphics options, e.g. bold, dotted, filled; cf. Section 2.3
|
43
|
+
'target', # if URL is set, determines browser window for URL
|
44
|
+
'tooltip', # default: label, tooltip annotation for node
|
45
|
+
'URL', # URL associated with node (format-dependent)
|
46
|
+
'width', # default: .75; width in inches
|
47
|
+
].freeze
|
48
|
+
|
49
|
+
# maintained for backward compatibility or rdot internal
|
50
|
+
NODE_OPTS_LGCY = [
|
51
|
+
'bottomlabel', # auxiliary label for nodes of shape M*
|
52
|
+
'bgcolor',
|
53
|
+
'rank',
|
54
|
+
'toplabel' # auxiliary label for nodes of shape M*
|
55
|
+
].freeze
|
46
56
|
|
47
57
|
# options for edge declaration
|
48
|
-
|
49
58
|
EDGE_OPTS = [
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
59
|
+
'arrowhead', # default: normal; style of arrowhead at head end
|
60
|
+
'arrowsize', # default: 1.0; scaling factor for arrowheads
|
61
|
+
'arrowtail', # default: normal; style of arrowhead at tail end
|
62
|
+
'color', # default: black; edge stroke color
|
63
|
+
'colorscheme', # default: X11; scheme for interpreting color names
|
64
|
+
'comment', # any string (format-dependent)
|
65
|
+
'constraint', # default: true use edge to affect node ranking
|
66
|
+
'decorate', # if set, draws a line connecting labels with their edges
|
67
|
+
'dir', # default: forward; forward, back, both, or none
|
68
|
+
'edgeURL', # URL attached to non-label part of edge
|
69
|
+
'edgehref', # synonym for edgeURL
|
70
|
+
'edgetarget', # if URL is set, determines browser window for URL
|
71
|
+
'edgetooltip', # default: label; tooltip annotation for non-label part of edge
|
72
|
+
'fontcolor', # default: black type face color
|
73
|
+
'fontname', # default: Times-Roman; font family
|
74
|
+
'fontsize', # default: 14; point size of label
|
75
|
+
'headclip', # default: true; if false, edge is not clipped to head node boundary
|
76
|
+
'headhref', # synonym for headURL
|
77
|
+
'headlabel', # default: label; placed near head of edge
|
78
|
+
'headport', # n,ne,e,se,s,sw,w,nw
|
79
|
+
'headtarget', # if headURL is set, determines browser window for URL
|
80
|
+
'headtooltip', # default: label; tooltip annotation near head of edge
|
81
|
+
'headURL', # URL attached to head label if output format is ismap
|
82
|
+
'href', # alias for URL
|
83
|
+
'id', # any string (user-defined output object tags)
|
84
|
+
'label', # edge label
|
85
|
+
'labelangle', # default: -25.0; angle in degrees which head or tail label is rotated off edge
|
86
|
+
'labeldistance', # default: 1.0; scaling factor for distance of head or tail label from node
|
87
|
+
'labelfloat', # default: false; lessen constraints on edge label placement
|
88
|
+
'labelfontcolor', # default: black; type face color for head and tail labels
|
89
|
+
'labelfontname', # default: Times-Roman; font family for head and tail labels
|
90
|
+
'labelfontsize', # default: 14 point size for head and tail labels
|
91
|
+
'labelhref', # synonym for labelURL
|
92
|
+
'labelURL', # URL for label, overrides edge URL
|
93
|
+
'labeltarget', # if URL or labelURL is set, determines browser window for URL
|
94
|
+
'labeltooltip', # default: label; tooltip annotation near label
|
95
|
+
'layer', # default: overlay range; all, id or id:id
|
96
|
+
'lhead', # name of cluster to use as head of edge
|
97
|
+
'ltail', # name of cluster to use as tail of edge
|
98
|
+
'minlen', # default: 1 minimum rank distance between head and tail
|
99
|
+
'penwidth', # default: 1.0; width of pen for drawing boundaries, in points
|
100
|
+
'samehead', # tag for head node; edge heads with the same tag are merged onto the same port
|
101
|
+
'sametail', # tag for tail node; edge tails with the same tag are merged onto the same port
|
102
|
+
'style', # graphics options, e.g. bold, dotted, filled; cf. Section 2.3
|
103
|
+
'weight', # default: 1; integer cost of stretching an edge
|
104
|
+
'tailclip', # default: true; if false, edge is not clipped to tail node boundary
|
105
|
+
'tailhref', # synonym for tailURL
|
106
|
+
'taillabel', # label placed near tail of edge
|
107
|
+
'tailport', # n,ne,e,se,s,sw,w,nw
|
108
|
+
'tailtarget', # if tailURL is set, determines browser window for URL
|
109
|
+
'tailtooltip', # default: label; tooltip annotation near tail of edge
|
110
|
+
'tailURL', # URL attached to tail label if output format is ismap
|
111
|
+
'target', # if URL is set, determines browser window for URL
|
112
|
+
'tooltip' # default: label; tooltip annotation for edge
|
113
|
+
].freeze
|
114
|
+
|
115
|
+
# maintained for backward compatibility or rdot internal
|
116
|
+
EDGE_OPTS_LGCY = [].freeze
|
86
117
|
|
87
118
|
# options for graph declaration
|
88
|
-
|
89
119
|
GRAPH_OPTS = [
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
120
|
+
'aspect', # controls aspect ratio adjustment
|
121
|
+
'bgcolor', # background color for drawing, plus initial fill color
|
122
|
+
'center', # default: false; center draing on page
|
123
|
+
'clusterrank', # default: local; may be "global" or "none"
|
124
|
+
'color', # default: black; for clusters, outline color, and fill color if
|
125
|
+
# fillcolor not defined
|
126
|
+
'colorscheme', # default: X11; scheme for interpreting color names
|
127
|
+
'comment', # any string (format-dependent)
|
128
|
+
'compound', # default: false; allow edges between clusters
|
129
|
+
'concentrate', # default: false; enables edge concentrators
|
130
|
+
'dpi', # default: 96; dots per inch for image output
|
131
|
+
'fillcolor', # default: black; cluster fill color
|
132
|
+
'fontcolor', # default: black; type face color
|
133
|
+
'fontname', # default: Times-Roman; font family
|
134
|
+
'fontnames', # svg, ps, gd (SVG only)
|
135
|
+
'fontpath', # list of directories to search for fonts
|
136
|
+
'fontsize', # default: 14; point size of label
|
137
|
+
'id', # any string (user-defined output object tags)
|
138
|
+
'label', # any string
|
139
|
+
'labeljust', # default: centered; "l" and "r" for left- and right-justified
|
140
|
+
# cluster labels, respectively
|
141
|
+
'labelloc', # default: top; "t" and "b" for top- and bottom-justified
|
142
|
+
# cluster labels, respectively
|
143
|
+
'landscape', # if true, means orientation=landscape
|
144
|
+
'layers', # id:id:id...
|
145
|
+
'layersep', # default: : ; specifies separator character to split layers'
|
146
|
+
'margin', # default: .5; margin included in page, inches
|
147
|
+
'mclimit', # default: 1.0; scale factor for mincross iterations
|
148
|
+
'nodesep', # default: .25; separation between nodes, in inches.
|
149
|
+
'nojustify', # default: false; if true, justify to label, not graph
|
150
|
+
'nslimit', # if set to "f", bounds network simplex iterations by
|
151
|
+
# (f)(number of nodes) when setting x-coordinates
|
152
|
+
'nslimit1', # if set to "f", bounds network simplex iterations by
|
153
|
+
# (f)(number of nodes) when ranking nodes
|
154
|
+
'ordering', # if "out" out edge order is preserved
|
155
|
+
'orientation', # default: portrait; if "rotate" is not used and the value is
|
156
|
+
# "landscape", use landscape orientation
|
157
|
+
'outputorder', # default: breadthfirst; or nodesfirst, edgesfirst
|
158
|
+
'page', # unit of pagination, e.g. "8.5,11"
|
159
|
+
'pagedir', # default: BL; traversal order of pages
|
160
|
+
'pencolor', # default: black; color for drawing cluster boundaries
|
161
|
+
'penwidth', # default: 1.0; width of pen for drawing boundaries, in points
|
162
|
+
'peripheries', # default: 1; shape-dependent number of node boundaries
|
163
|
+
'rank', # "same", "min", "max", "source", or "sink"
|
164
|
+
'rankdir', # default: TB; "LR" (left to right) or "TB" (top to bottom)
|
165
|
+
'ranksep', # default: .75; separation between ranks, in inches.
|
166
|
+
'ratio', # approximate aspect ratio desired, "fill" or "auto"
|
167
|
+
'remincross', # default: true; whether to run edge crossing minimization
|
168
|
+
# a second time when there are multiple clusters
|
169
|
+
'rotate', # If 90, set orientation to landscape
|
170
|
+
'samplepoints', # default: 8; number of points used to represent ellipses
|
171
|
+
# and circles on output
|
172
|
+
'searchsize', # default: 30; maximum edges with negative cut values to check
|
173
|
+
# when looking for a minimum one during network simplex
|
174
|
+
'size', # maximum drawing size, in inches
|
175
|
+
'splines', # draw edges as splines, polylines, lines
|
176
|
+
'style', # graphics options, e.g. "filled" for clusters
|
177
|
+
'stylesheet', # pathname or URL to XML style sheet for SVG
|
178
|
+
'target', # if URL is set, determines browser window for URL
|
179
|
+
'tooltip', # default: label; tooltip annotation for cluster
|
180
|
+
'truecolor', # if set, force 24 bit or indexed color in image output
|
181
|
+
'viewport', # clipping window on output
|
182
|
+
'URL', # URL associated with graph (format-dependent)
|
183
|
+
].freeze
|
184
|
+
|
185
|
+
# maintained for backward compatibility or rdot internal
|
186
|
+
GRAPH_OPTS_LGCY = [
|
187
|
+
'layerseq'
|
188
|
+
].freeze
|
135
189
|
|
136
190
|
# Ancestor of Edge, Node, and Graph.
|
137
191
|
#
|
@@ -179,16 +233,15 @@ module RGL
|
|
179
233
|
# Return a quoted version of the label otherwise.
|
180
234
|
'"' + label.split(/(\\n|\\r|\\l)/).collect do |part|
|
181
235
|
case part
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
236
|
+
when "\\n", "\\r", "\\l"
|
237
|
+
part
|
238
|
+
else
|
239
|
+
part.gsub('\\', '\\\\\\\\').gsub('"', '\\\\"').gsub("\n", '\\n')
|
186
240
|
end
|
187
241
|
end.join + '"'
|
188
242
|
end
|
189
243
|
end
|
190
244
|
|
191
|
-
|
192
245
|
# Ports are used when a Node instance has its `shape' option set to
|
193
246
|
# _record_ or _Mrecord_. Ports can be nested.
|
194
247
|
#
|
@@ -244,7 +297,7 @@ module RGL
|
|
244
297
|
# option which, if specified, must be an Enumerable containing a list of
|
245
298
|
# ports.
|
246
299
|
#
|
247
|
-
def initialize(params = {}, option_list = NODE_OPTS)
|
300
|
+
def initialize(params = {}, option_list = NODE_OPTS+NODE_OPTS_LGCY)
|
248
301
|
super(params, option_list)
|
249
302
|
@ports = params['ports'] ? params['ports'] : []
|
250
303
|
end
|
@@ -287,11 +340,10 @@ module RGL
|
|
287
340
|
leader + quote_ID(@name) unless @name.nil?
|
288
341
|
else
|
289
342
|
leader + (@name.nil? ? '' : quote_ID(@name) + " ") + "[\n" +
|
290
|
-
|
291
|
-
|
343
|
+
stringified_options + "\n" +
|
344
|
+
leader + "]"
|
292
345
|
end
|
293
346
|
end
|
294
|
-
|
295
347
|
end # class Node
|
296
348
|
|
297
349
|
# A graph representation. Whether or not it is rendered as directed or
|
@@ -306,7 +358,7 @@ module RGL
|
|
306
358
|
# option which, if specified, must be an Enumerable containing a list of
|
307
359
|
# nodes, edges, and/or subgraphs.
|
308
360
|
#
|
309
|
-
def initialize(params = {}, option_list = GRAPH_OPTS)
|
361
|
+
def initialize(params = {}, option_list = GRAPH_OPTS+GRAPH_OPTS_LGCY)
|
310
362
|
super(params, option_list)
|
311
363
|
@elements = params['elements'] ? params['elements'] : []
|
312
364
|
@dot_string = 'graph'
|
@@ -368,9 +420,8 @@ module RGL
|
|
368
420
|
end.join("\n\n")
|
369
421
|
|
370
422
|
hdr + (options.empty? ? '' : options + "\n\n") +
|
371
|
-
|
423
|
+
(elements.empty? ? '' : elements + "\n") + leader + "}"
|
372
424
|
end
|
373
|
-
|
374
425
|
end # class Graph
|
375
426
|
|
376
427
|
# A digraph is a directed graph representation which is the same as a Graph
|
@@ -385,7 +436,7 @@ module RGL
|
|
385
436
|
# option which, if specified, must be an Enumerable containing a list of
|
386
437
|
# nodes, edges, and/or subgraphs.
|
387
438
|
#
|
388
|
-
def initialize(params = {}, option_list = GRAPH_OPTS)
|
439
|
+
def initialize(params = {}, option_list = GRAPH_OPTS+GRAPH_OPTS_LGCY)
|
389
440
|
super(params, option_list)
|
390
441
|
@dot_string = 'digraph'
|
391
442
|
end
|
@@ -404,7 +455,7 @@ module RGL
|
|
404
455
|
# option which, if specified, must be an Enumerable containing a list of
|
405
456
|
# nodes, edges, and/or subgraphs.
|
406
457
|
#
|
407
|
-
def initialize(params = {}, option_list = GRAPH_OPTS)
|
458
|
+
def initialize(params = {}, option_list = GRAPH_OPTS+GRAPH_OPTS_LGCY)
|
408
459
|
super(params, option_list)
|
409
460
|
@dot_string = 'subgraph'
|
410
461
|
end
|
@@ -427,7 +478,7 @@ module RGL
|
|
427
478
|
# edge options. The _option_list_ parameter restricts those options to the
|
428
479
|
# list of valid names it contains.
|
429
480
|
#
|
430
|
-
def initialize(params = {}, option_list = EDGE_OPTS)
|
481
|
+
def initialize(params = {}, option_list = EDGE_OPTS+EDGE_OPTS_LGCY)
|
431
482
|
super(params, option_list)
|
432
483
|
@from = params['from'] ? params['from'] : nil
|
433
484
|
@to = params['to'] ? params['to'] : nil
|
@@ -452,8 +503,8 @@ module RGL
|
|
452
503
|
leader + quote_ID(f_s) + ' ' + edge_link + ' ' + quote_ID(t_s)
|
453
504
|
else
|
454
505
|
leader + quote_ID(f_s) + ' ' + edge_link + ' ' + quote_ID(t_s) + " [\n" +
|
455
|
-
|
456
|
-
|
506
|
+
stringified_options + "\n" +
|
507
|
+
leader + "]"
|
457
508
|
end
|
458
509
|
end
|
459
510
|
|
data/test/dot_test.rb
CHANGED
@@ -13,7 +13,7 @@ class TestDot < Test::Unit::TestCase
|
|
13
13
|
graph = RGL::DirectedAdjacencyGraph["a", "b"]
|
14
14
|
|
15
15
|
begin
|
16
|
-
dot
|
16
|
+
dot = graph.to_dot_graph.to_s
|
17
17
|
|
18
18
|
first_vertex_id = "a"
|
19
19
|
second_vertex_id = "b"
|
@@ -29,31 +29,29 @@ class TestDot < Test::Unit::TestCase
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
33
|
-
|
32
|
+
def test_dot_digraph_with_complicated_options
|
33
|
+
graph = RGL::DirectedAdjacencyGraph['a','b', 'c','d', 'a','c']
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
key = "#{b}-#{e}"
|
39
|
-
edge_labels[key] = "#{b} to #{e}"
|
40
|
-
end
|
41
|
-
|
42
|
-
vertex_fontcolors = {'a' => 'green', 'b' => 'blue'}
|
43
|
-
vertex_fontcolor_setting = Proc.new{|v| vertex_fontcolors[v]}
|
44
|
-
vertex_settings = {'fontcolor' => vertex_fontcolor_setting, 'fontsize' => 12}
|
45
|
-
|
46
|
-
edge_label_setting = Proc.new{|b, e| edge_labels["#{b}-#{e}"]}
|
47
|
-
edge_settings = {'color' => 'red', 'label' => edge_label_setting}
|
48
|
-
dot_options = {'edge' => edge_settings,'vertex' => vertex_settings}
|
49
|
-
dot = graph.to_dot_graph(dot_options).to_s
|
35
|
+
graph.set_vertex_options('a', label: 'This is A', shape: 'box3d', fontcolor: 'green', fontsize: 16)
|
36
|
+
graph.set_vertex_options('b', label: 'This is B', shape: 'tab', fontcolor: 'red', fontsize: 14)
|
37
|
+
graph.set_vertex_options('c', shape: 'tab', fontcolor: 'blue')
|
50
38
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
39
|
+
graph.set_edge_options('a', 'b', label: 'NotCapitalEdge', style: 'dotted', dir: 'back', color: 'magenta')
|
40
|
+
graph.set_edge_options('a', 'c', weight: 5, color: 'blue')
|
41
|
+
|
42
|
+
graph_options = {
|
43
|
+
"rankdir" => "LR",
|
44
|
+
"labelloc" => "t",
|
45
|
+
"label" => "Graph\n (generated #{Time.now.utc})"
|
46
|
+
}
|
47
|
+
|
48
|
+
dot = graph.to_dot_graph(graph_options).to_s
|
49
|
+
|
50
|
+
assert_match(dot, /labelloc = t\n\s*/)
|
51
|
+
assert_match(dot, /rankdir = LR\n\s*/)
|
52
|
+
assert_match(dot, /a \[\n\s*fontcolor = green,\n\s*fontsize = 16,\n\s*shape = box3d,\n\s*label = "This is A"\n\s*/)
|
53
|
+
assert_match(dot, /b \[\n\s*fontcolor = red,\n\s*fontsize = 14,\n\s*shape = tab,\n\s*label = "This is B"\n\s*/)
|
54
|
+
assert_match(dot, /a -> b \[\n\s*color = magenta,\n\s*dir = back,\n\s*fontsize = 8,\n\s*label = NotCapitalEdge,\n\s*style = dotted\n\s*/)
|
57
55
|
end
|
58
56
|
|
59
57
|
def test_to_dot_graph
|
@@ -65,10 +63,6 @@ class TestDot < Test::Unit::TestCase
|
|
65
63
|
def graph.vertex_id(v)
|
66
64
|
"id-"+v.to_s
|
67
65
|
end
|
68
|
-
|
69
|
-
graph.write_to_graphic_file
|
70
|
-
rescue
|
71
|
-
puts "Graphviz not installed?"
|
72
|
-
end
|
66
|
+
graph.write_to_graphic_file
|
73
67
|
end
|
74
68
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rgl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Horst Duchene
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire: rgl/base
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-
|
12
|
+
date: 2023-05-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: stream
|