ruby-graphviz 1.0.9 → 1.1.0
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.
- checksums.yaml +4 -4
- data/.travis.yml +3 -2
- data/AUTHORS.rdoc +5 -1
- data/CHANGELOG.rdoc +10 -0
- data/README.rdoc +2 -1
- data/Rakefile +32 -24
- data/examples/sample70.rb +9 -0
- data/examples/sample71.rb +21 -0
- data/examples/sample72.rb +22 -0
- data/lib/ext/gvpr/dot2ruby.g +80 -62
- data/lib/graphviz.rb +51 -40
- data/lib/graphviz/attrs.rb +1 -1
- data/lib/graphviz/constants.rb +1 -1
- data/lib/graphviz/dot2ruby.rb +5 -2
- data/lib/graphviz/edge.rb +181 -176
- data/lib/graphviz/node.rb +6 -1
- data/lib/graphviz/theory.rb +7 -7
- data/lib/graphviz/utils.rb +6 -22
- data/ruby-graphviz.gemspec +1 -5
- data/test/helper.rb +13 -0
- data/test/test_dot_script.rb +45 -41
- data/test/test_examples.rb +20 -30
- data/test/test_graph.rb +14 -3
- data/test/test_search.rb +1 -4
- data/test/test_subgraph.rb +14 -3
- data/test/test_theory.rb +15 -5
- data/test/test_types.rb +1 -3
- data/test/test_utils_colors.rb +1 -3
- metadata +26 -53
- data/test/support.rb +0 -105
data/lib/graphviz/attrs.rb
CHANGED
@@ -59,7 +59,7 @@ class GraphViz
|
|
59
59
|
end
|
60
60
|
|
61
61
|
begin
|
62
|
-
value = GraphViz::Types.const_get(@attributes[key.to_s]).new(
|
62
|
+
value = GraphViz::Types.const_get(@attributes[key.to_s]).new(value)
|
63
63
|
rescue => e
|
64
64
|
raise AttributeException, "Invalid value `#{value}` for attribute `#{key}` : #{e}"
|
65
65
|
end
|
data/lib/graphviz/constants.rb
CHANGED
data/lib/graphviz/dot2ruby.rb
CHANGED
@@ -24,13 +24,16 @@ class Dot2Ruby #:nodoc:
|
|
24
24
|
def initialize( xGVPath, xOutFile, xOutFormat = nil ) #:nodoc:
|
25
25
|
paths = (xGVPath.nil?) ? [] : [xGVPath]
|
26
26
|
@xGvprPath = find_executable( 'gvpr', paths )
|
27
|
+
if (@xGvprPath.blank?)
|
28
|
+
raise Exception, "GraphViz is not installed. Please be sure that 'gvpr' is on the search path'"
|
29
|
+
end
|
27
30
|
@xOutFile = xOutFile
|
28
31
|
@xOutFormat = xOutFormat || "_"
|
29
32
|
@gvprScript = GraphViz::Ext.find( "dot2ruby.g" )
|
30
33
|
end
|
31
34
|
|
32
35
|
def run( xFile ) #:nodoc:
|
33
|
-
xCmd =
|
36
|
+
xCmd = [@xGvprPath, '-f', @gvprScript, '-a', @xOutFormat, xFile]
|
34
37
|
xOutput = output_from_command( xCmd )
|
35
38
|
if @xOutFile.nil?
|
36
39
|
puts xOutput
|
@@ -42,7 +45,7 @@ class Dot2Ruby #:nodoc:
|
|
42
45
|
end
|
43
46
|
|
44
47
|
def eval( xFile ) #:nodoc:
|
45
|
-
xCmd =
|
48
|
+
xCmd = [@xGvprPath, '-f', @gvprScript, '-a', '-', xFile]
|
46
49
|
xOutput = output_from_command( xCmd )
|
47
50
|
instance_eval(xOutput)
|
48
51
|
return @_graph_eval
|
data/lib/graphviz/edge.rb
CHANGED
@@ -18,180 +18,185 @@ require 'graphviz/attrs'
|
|
18
18
|
require 'graphviz/constants'
|
19
19
|
|
20
20
|
class GraphViz
|
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
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
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
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
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
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
21
|
+
class Edge
|
22
|
+
include GraphViz::Constants
|
23
|
+
|
24
|
+
# Create a new edge
|
25
|
+
#
|
26
|
+
# In:
|
27
|
+
# * vNodeOne : First node (can be a GraphViz::Node or a node ID)
|
28
|
+
# * vNodeTwo : Second node (can be a GraphViz::Node or a node ID)
|
29
|
+
# * parent_graph : Graph
|
30
|
+
def initialize( vNodeOne, vNodeTwo, parent_graph )
|
31
|
+
@node_one_id, @node_one_port = getNodeNameAndPort( vNodeOne )
|
32
|
+
@node_two_id, @node_two_port = getNodeNameAndPort( vNodeTwo )
|
33
|
+
|
34
|
+
@parent_graph = parent_graph
|
35
|
+
@edge_attributes = GraphViz::Attrs::new( nil, "edge", EDGESATTRS )
|
36
|
+
@index = nil
|
37
|
+
|
38
|
+
unless @parent_graph.directed?
|
39
|
+
(@parent_graph.find_node(@node_one_id) || @parent_graph.add_nodes(@node_one_id)).incidents << (@parent_graph.find_node(@node_two_id) || @parent_graph.add_nodes(@node_two_id))
|
40
|
+
(@parent_graph.find_node(@node_two_id) || @parent_graph.add_nodes(@node_two_id)).neighbors << (@parent_graph.find_node(@node_one_id) || @parent_graph.add_nodes(@node_one_id))
|
41
|
+
end
|
42
|
+
(@parent_graph.find_node(@node_one_id) || @parent_graph.add_nodes(@node_one_id)).neighbors << (@parent_graph.find_node(@node_two_id) || @parent_graph.add_nodes(@node_two_id))
|
43
|
+
(@parent_graph.find_node(@node_two_id) || @parent_graph.add_nodes(@node_two_id)).incidents << (@parent_graph.find_node(@node_one_id) || @parent_graph.add_nodes(@node_one_id))
|
44
|
+
end
|
45
|
+
|
46
|
+
# Return the node one as string (so with port if any)
|
47
|
+
def node_one(with_port = true, escaped = true)
|
48
|
+
if not(@node_one_port and with_port)
|
49
|
+
escaped ? GraphViz.escape(@node_one_id) : @node_one_id
|
50
|
+
else
|
51
|
+
escaped ? GraphViz.escape(@node_one_id, :force => true) + ":#{@node_one_port}" : "#{@node_one_id}:#{@node_one_port}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
alias :tail_node :node_one
|
55
|
+
|
56
|
+
# Return the node two as string (so with port if any)
|
57
|
+
def node_two(with_port = true, escaped = true)
|
58
|
+
if not(@node_two_port and with_port)
|
59
|
+
escaped ? GraphViz.escape(@node_two_id) : @node_two_id
|
60
|
+
else
|
61
|
+
escaped ? GraphViz.escape(@node_two_id, :force => true) + ":#{@node_two_port}" : "#{@node_two_id}:#{@node_two_port}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
alias :head_node :node_two
|
65
|
+
|
66
|
+
# Return the index of the edge
|
67
|
+
def index
|
68
|
+
@index
|
69
|
+
end
|
70
|
+
def index=(i) #:nodoc:
|
71
|
+
@index = i if @index == nil
|
72
|
+
end
|
73
|
+
|
74
|
+
# Set value +attribute_value+ to the edge attribute +attribute_name+
|
75
|
+
def []=( attribute_name, attribute_value )
|
76
|
+
attribute_value = attribute_value.to_s if attribute_value.class == Symbol
|
77
|
+
@edge_attributes[attribute_name.to_s] = attribute_value
|
78
|
+
end
|
79
|
+
|
80
|
+
# Set values for edge attributes or
|
81
|
+
# get the value of the given edge attribute +attribute_name+
|
82
|
+
def []( attribute_name )
|
83
|
+
# Modification by axgle (http://github.com/axgle)
|
84
|
+
if Hash === attribute_name
|
85
|
+
attribute_name.each do |key, value|
|
86
|
+
self[key] = value
|
87
|
+
end
|
88
|
+
else
|
89
|
+
if @edge_attributes[attribute_name.to_s]
|
90
|
+
@edge_attributes[attribute_name.to_s].clone
|
91
|
+
else
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
#
|
98
|
+
# Calls block once for each attribute of the edge, passing the name and value to the
|
99
|
+
# block as a two-element array.
|
100
|
+
#
|
101
|
+
# If global is set to false, the block does not receive the attributes set globally
|
102
|
+
#
|
103
|
+
def each_attribute(global = true, &b)
|
104
|
+
attrs = @edge_attributes.to_h
|
105
|
+
if global
|
106
|
+
attrs = pg.edge.to_h.merge attrs
|
107
|
+
end
|
108
|
+
attrs.each do |k,v|
|
109
|
+
yield(k,v)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
def each_attribut(global = true, &b)
|
113
|
+
warn "`GraphViz::Edge#each_attribut` is deprecated, please use `GraphViz::Edge#each_attribute`"
|
114
|
+
each_attribute(global, &b)
|
115
|
+
end
|
116
|
+
|
117
|
+
def <<( node ) #:nodoc:
|
118
|
+
n = @parent_graph.get_node(@node_two_id)
|
119
|
+
|
120
|
+
GraphViz::commonGraph( node, n ).add_edges( n, node )
|
121
|
+
end
|
122
|
+
alias :> :<< #:nodoc:
|
123
|
+
alias :- :<< #:nodoc:
|
124
|
+
alias :>> :<< #:nodoc:
|
125
|
+
|
126
|
+
#
|
127
|
+
# Return the root graph
|
128
|
+
#
|
129
|
+
def root_graph
|
130
|
+
return( (self.pg.nil?) ? nil : self.pg.root_graph )
|
131
|
+
end
|
132
|
+
|
133
|
+
def pg #:nodoc:
|
134
|
+
@parent_graph
|
135
|
+
end
|
136
|
+
|
137
|
+
# Set edge attributes
|
138
|
+
#
|
139
|
+
# Example :
|
140
|
+
# e = graph.add_edges( ... )
|
141
|
+
# ...
|
142
|
+
# e.set { |_e|
|
143
|
+
# _e.color = "blue"
|
144
|
+
# _e.fontcolor = "red"
|
145
|
+
# }
|
146
|
+
def set( &b )
|
147
|
+
yield( self )
|
148
|
+
end
|
149
|
+
|
150
|
+
# Add edge options
|
151
|
+
# use edge.<option>=<value> or edge.<option>( <value> )
|
152
|
+
def method_missing( idName, *args, &block ) #:nodoc:
|
153
|
+
return if idName == :to_ary # ruby 1.9.2 fix
|
154
|
+
xName = idName.id2name
|
155
|
+
|
156
|
+
self[xName.gsub( /=$/, "" )]=args[0]
|
157
|
+
end
|
158
|
+
|
159
|
+
def output( oGraphType ) #:nodoc:
|
160
|
+
xLink = " -> "
|
161
|
+
if oGraphType == "graph"
|
162
|
+
xLink = " -- "
|
163
|
+
end
|
164
|
+
|
165
|
+
# reserved words, they aren't accepted in dot as node name
|
166
|
+
reserved_names = ["node", "edge","graph", "digraph", "subgraph", "strict"]
|
167
|
+
|
168
|
+
xOut = reserved_names.include?(self.node_one) ? "" << "_" + self.node_one : "" << self.node_one
|
169
|
+
xOut = xOut << xLink
|
170
|
+
xOut = reserved_names.include?(self.node_two) ? xOut << "_" + self.node_two : xOut << self.node_two
|
171
|
+
xAttr = ""
|
172
|
+
xSeparator = ""
|
173
|
+
@edge_attributes.data.each do |k, v|
|
174
|
+
xAttr << xSeparator + k + " = " + v.to_gv
|
175
|
+
xSeparator = ", "
|
176
|
+
end
|
177
|
+
if xAttr.length > 0
|
178
|
+
xOut << " [" + xAttr + "]"
|
179
|
+
end
|
180
|
+
xOut << ";"
|
181
|
+
|
182
|
+
return( xOut )
|
183
|
+
end
|
184
|
+
|
185
|
+
private
|
186
|
+
def getNodeNameAndPort( node )
|
187
|
+
name, port = nil, nil
|
188
|
+
if node.class == Hash
|
189
|
+
node.each do |k, v|
|
190
|
+
name, port = getNodeNameAndPort(k)
|
191
|
+
port = v
|
192
|
+
end
|
193
|
+
elsif node.class == String
|
194
|
+
name = node
|
195
|
+
else
|
196
|
+
name = node.id
|
197
|
+
end
|
198
|
+
|
199
|
+
return name, port
|
200
|
+
end
|
201
|
+
end
|
197
202
|
end
|
data/lib/graphviz/node.rb
CHANGED
@@ -134,11 +134,16 @@ class GraphViz
|
|
134
134
|
end
|
135
135
|
|
136
136
|
def output #:nodoc:
|
137
|
+
# reserved words, they aren't accepted in dot as node name
|
138
|
+
reserved_names = ["node", "edge","graph", "digraph", "subgraph", "strict"]
|
137
139
|
#node_id = @node_id.clone
|
138
140
|
#node_id = '"' << node_id << '"' if node_id.match( /^[a-zA-Z_]+[a-zA-Z0-9_\.]*$/ ).nil?
|
139
141
|
node_id = GraphViz.escape(@node_id)
|
140
142
|
|
141
|
-
|
143
|
+
# add a check to see if the node names are valid
|
144
|
+
# if they aren't is added an _ before
|
145
|
+
# and the print staies the same, because of the label
|
146
|
+
xOut = reserved_names.include?(node_id) ? "" << "_" + node_id : "" << node_id
|
142
147
|
xAttr = ""
|
143
148
|
xSeparator = ""
|
144
149
|
|
data/lib/graphviz/theory.rb
CHANGED
@@ -11,8 +11,8 @@ class GraphViz
|
|
11
11
|
matrix = GraphViz::Math::Matrix.new( @graph.node_count, @graph.node_count )
|
12
12
|
|
13
13
|
@graph.each_edge { |e|
|
14
|
-
x = @graph.get_node(e.node_one( false
|
15
|
-
y = @graph.get_node(e.node_two( false
|
14
|
+
x = @graph.get_node(e.node_one(false, false)).index
|
15
|
+
y = @graph.get_node(e.node_two(false, false)).index
|
16
16
|
matrix[x+1, y+1] = 1
|
17
17
|
matrix[y+1, x+1] = 1 if @graph.type == "graph"
|
18
18
|
}
|
@@ -28,8 +28,8 @@ class GraphViz
|
|
28
28
|
@graph.each_edge { |e|
|
29
29
|
x = e.index
|
30
30
|
|
31
|
-
nstart = @graph.get_node(e.node_one( false
|
32
|
-
nend = @graph.get_node(e.node_two( false
|
31
|
+
nstart = @graph.get_node(e.node_one(false, false)).index
|
32
|
+
nend = @graph.get_node(e.node_two(false, false)).index
|
33
33
|
|
34
34
|
matrix[nstart+1, x+1] = 1
|
35
35
|
matrix[nend+1, x+1] = tail
|
@@ -48,7 +48,7 @@ class GraphViz
|
|
48
48
|
end
|
49
49
|
|
50
50
|
@graph.each_edge do |e|
|
51
|
-
degree += 1 if e.node_one(false) == name or e.node_two(false) == name
|
51
|
+
degree += 1 if e.node_one(false, false) == name or e.node_two(false, false) == name
|
52
52
|
end
|
53
53
|
|
54
54
|
return degree
|
@@ -246,8 +246,8 @@ class GraphViz
|
|
246
246
|
matrix = GraphViz::Math::Matrix.new( @graph.node_count, @graph.node_count, (1.0/0.0) )
|
247
247
|
|
248
248
|
@graph.each_edge { |e|
|
249
|
-
x = @graph.get_node(e.node_one( false
|
250
|
-
y = @graph.get_node(e.node_two( false
|
249
|
+
x = @graph.get_node(e.node_one(false, false)).index
|
250
|
+
y = @graph.get_node(e.node_two(false, false)).index
|
251
251
|
unless x == y
|
252
252
|
weight = ((e[:weight].nil?) ? 1 : e[:weight].to_f)
|
253
253
|
matrix[x+1, y+1] = weight
|