ruby-graphviz_c 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 +7 -0
- data/.gemrc +0 -0
- data/.gitignore +9 -0
- data/.travis.yml +7 -0
- data/AUTHORS.rdoc +33 -0
- data/CHANGELOG.rdoc +287 -0
- data/COPYING.rdoc +133 -0
- data/Gemfile +4 -0
- data/README.rdoc +206 -0
- data/Rakefile +71 -0
- data/bin/dot2ruby +91 -0
- data/bin/gem2gv +165 -0
- data/bin/git2gv +167 -0
- data/bin/ruby2gv +234 -0
- data/bin/xml2gv +96 -0
- data/examples/dot/JSP.dot +52 -0
- data/examples/dot/balanced.dot +36 -0
- data/examples/dot/cluster.dot +30 -0
- data/examples/dot/dotgraph.dot +28 -0
- data/examples/dot/fsm.dot +20 -0
- data/examples/dot/genetic.dot +118 -0
- data/examples/dot/hello.dot +1 -0
- data/examples/dot/hello_test.rb +33 -0
- data/examples/dot/lion_share.dot +103 -0
- data/examples/dot/prof.dot +150 -0
- data/examples/dot/psg.dot +28 -0
- data/examples/dot/rank.dot +6 -0
- data/examples/dot/sdh.dot +284 -0
- data/examples/dot/siblings.dot +492 -0
- data/examples/dot/so-sample001.gv +30 -0
- data/examples/dot/so-sample002.gv +33 -0
- data/examples/dot/so-sample003.gv +45 -0
- data/examples/dot/test.dot +17 -0
- data/examples/dot/test_parse.rb +13 -0
- data/examples/dot/this_crach_with_dot_2.20.dot +24 -0
- data/examples/dot/unix.dot +104 -0
- data/examples/graphml/attributes.ext.graphml +12 -0
- data/examples/graphml/attributes.graphml +40 -0
- data/examples/graphml/cluster.graphml +75 -0
- data/examples/graphml/failed_graph.graphml +461 -0
- data/examples/graphml/hyper.graphml +29 -0
- data/examples/graphml/nested.graphml +54 -0
- data/examples/graphml/port.graphml +32 -0
- data/examples/graphml/simple.graphml +30 -0
- data/examples/hello.png +0 -0
- data/examples/rgv/rgv.ps +125 -0
- data/examples/rgv/test_rgv.rb +12 -0
- data/examples/sample01.rb +32 -0
- data/examples/sample02.rb +42 -0
- data/examples/sample03.rb +31 -0
- data/examples/sample04.rb +22 -0
- data/examples/sample05.rb +32 -0
- data/examples/sample06.rb +46 -0
- data/examples/sample07.rb +23 -0
- data/examples/sample08.rb +34 -0
- data/examples/sample09.rb +50 -0
- data/examples/sample10.rb +50 -0
- data/examples/sample11.rb +42 -0
- data/examples/sample12.rb +55 -0
- data/examples/sample13.rb +48 -0
- data/examples/sample14.rb +44 -0
- data/examples/sample15.rb +25 -0
- data/examples/sample16.rb +8 -0
- data/examples/sample17.rb +92 -0
- data/examples/sample18.rb +24 -0
- data/examples/sample19.rb +59 -0
- data/examples/sample20.rb +47 -0
- data/examples/sample21.rb +12 -0
- data/examples/sample22.rb +10 -0
- data/examples/sample23.rb +11 -0
- data/examples/sample24.rb +11 -0
- data/examples/sample25.rb +11 -0
- data/examples/sample26.rb +8 -0
- data/examples/sample27.rb +8 -0
- data/examples/sample28.rb +12 -0
- data/examples/sample29.rb +8 -0
- data/examples/sample30.rb +12 -0
- data/examples/sample31.rb +10 -0
- data/examples/sample32.rb +14 -0
- data/examples/sample33.rb +43 -0
- data/examples/sample34.rb +29 -0
- data/examples/sample35.rb +43 -0
- data/examples/sample36.rb +35 -0
- data/examples/sample37.rb +87 -0
- data/examples/sample38.rb +12 -0
- data/examples/sample39.rb +11 -0
- data/examples/sample40.rb +17 -0
- data/examples/sample41.rb +8 -0
- data/examples/sample42.rb +35 -0
- data/examples/sample43.rb +26 -0
- data/examples/sample44.rb +97 -0
- data/examples/sample45.rb +24 -0
- data/examples/sample46.rb +43 -0
- data/examples/sample47.rb +7 -0
- data/examples/sample48.rb +62 -0
- data/examples/sample49.rb +10 -0
- data/examples/sample50.rb +215 -0
- data/examples/sample51.rb +37 -0
- data/examples/sample52.rb +62 -0
- data/examples/sample53.rb +26 -0
- data/examples/sample54.rb +26 -0
- data/examples/sample55.rb +9 -0
- data/examples/sample56.rb +10 -0
- data/examples/sample57.rb +8 -0
- data/examples/sample58.rb +33 -0
- data/examples/sample59.rb +14 -0
- data/examples/sample60.rb +12 -0
- data/examples/sample61.rb +12 -0
- data/examples/sample62.rb +24 -0
- data/examples/sample63.rb +32 -0
- data/examples/sample64.rb +31 -0
- data/examples/sample65.rb +9 -0
- data/examples/sample66.rb +4 -0
- data/examples/sample67.rb +10 -0
- data/examples/sample68.rb +27 -0
- data/examples/sample69.rb +23 -0
- data/examples/sample70.rb +9 -0
- data/examples/sample99.rb +70 -0
- data/examples/sdlshapes/README +2 -0
- data/examples/sdlshapes/sdl.ps +655 -0
- data/examples/sdlshapes/sdlshapes.dot +78 -0
- data/examples/test.xml +26 -0
- data/examples/theory/pert.rb +47 -0
- data/examples/theory/tests.rb +87 -0
- data/lib/ext/gvpr/dot2ruby.g +185 -0
- data/lib/graphviz/attrs.rb +73 -0
- data/lib/graphviz/constants.rb +294 -0
- data/lib/graphviz/core_ext.rb +64 -0
- data/lib/graphviz/dot2ruby.rb +59 -0
- data/lib/graphviz/dot_script.rb +109 -0
- data/lib/graphviz/dsl.rb +67 -0
- data/lib/graphviz/edge.rb +197 -0
- data/lib/graphviz/elements.rb +39 -0
- data/lib/graphviz/ext.rb +17 -0
- data/lib/graphviz/family_tree/couple.rb +63 -0
- data/lib/graphviz/family_tree/generation.rb +39 -0
- data/lib/graphviz/family_tree/person.rb +120 -0
- data/lib/graphviz/family_tree/sibling.rb +13 -0
- data/lib/graphviz/family_tree.rb +118 -0
- data/lib/graphviz/graphml.rb +268 -0
- data/lib/graphviz/math/matrix.rb +221 -0
- data/lib/graphviz/node.rb +160 -0
- data/lib/graphviz/nothugly/nothugly.xsl +321 -0
- data/lib/graphviz/nothugly.rb +63 -0
- data/lib/graphviz/theory.rb +321 -0
- data/lib/graphviz/types/arrow_type.rb +32 -0
- data/lib/graphviz/types/color.rb +58 -0
- data/lib/graphviz/types/color_list.rb +24 -0
- data/lib/graphviz/types/esc_string.rb +20 -0
- data/lib/graphviz/types/gv_bool.rb +49 -0
- data/lib/graphviz/types/gv_double.rb +32 -0
- data/lib/graphviz/types/html_string.rb +18 -0
- data/lib/graphviz/types/lbl_string.rb +22 -0
- data/lib/graphviz/types/rect.rb +35 -0
- data/lib/graphviz/types/spline_type.rb +77 -0
- data/lib/graphviz/types.rb +22 -0
- data/lib/graphviz/utils/colors.rb +1018 -0
- data/lib/graphviz/utils.rb +70 -0
- data/lib/graphviz/xml.rb +119 -0
- data/lib/graphviz.rb +967 -0
- data/lib/ruby-graphviz.rb +1 -0
- data/man/dot2ruby.1 +66 -0
- data/man/dot2ruby.1.ronn +55 -0
- data/man/gem2gv.1 +60 -0
- data/man/gem2gv.1.ronn +47 -0
- data/man/git2gv.1 +48 -0
- data/man/git2gv.1.ronn +40 -0
- data/man/ruby2gv.1 +60 -0
- data/man/ruby2gv.1.ronn +47 -0
- data/man/xml2gv.1 +48 -0
- data/man/xml2gv.1.ronn +39 -0
- data/ruby-graphviz.gemspec +47 -0
- data/setup.rb +1585 -0
- data/test/helper.rb +13 -0
- data/test/support.rb +95 -0
- data/test/test_dot_script.rb +47 -0
- data/test/test_examples.rb +151 -0
- data/test/test_graph.rb +115 -0
- data/test/test_search.rb +29 -0
- data/test/test_subgraph.rb +27 -0
- data/test/test_theory.rb +98 -0
- data/test/test_types.rb +65 -0
- data/test/test_utils_colors.rb +52 -0
- metadata +301 -0
data/lib/graphviz/dsl.rb
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
require 'graphviz'
|
|
2
|
+
|
|
3
|
+
class GraphViz::DSL
|
|
4
|
+
attr_accessor :graph
|
|
5
|
+
|
|
6
|
+
# Create a new graph
|
|
7
|
+
def initialize(name, options = {}, &block)
|
|
8
|
+
@graph = GraphViz.new(name, options)
|
|
9
|
+
instance_eval(&block) if block
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def method_missing(sym, *args, &block) #:nodoc:
|
|
13
|
+
return @graph.get_graph(sym.to_s) unless @graph.get_graph(sym.to_s).nil?
|
|
14
|
+
return @graph.get_node(sym.to_s) unless @graph.get_node(sym.to_s).nil?
|
|
15
|
+
if(@graph.respond_to?(sym, true))
|
|
16
|
+
@graph.send(sym, *args)
|
|
17
|
+
elsif(block)
|
|
18
|
+
@graph.add_graph(GraphViz::DSL.new(sym, { :parent => @graph, :type => @graph.type }, &block).graph)
|
|
19
|
+
else
|
|
20
|
+
@graph.add_nodes(sym.to_s, *args)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Add a new node
|
|
25
|
+
def n(name)
|
|
26
|
+
return @graph.get_node(name) unless @graph.get_node(name.to_s).nil?
|
|
27
|
+
@graph.add_nodes(name)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Create edges
|
|
31
|
+
def e(*args)
|
|
32
|
+
e = nil
|
|
33
|
+
last = args.shift
|
|
34
|
+
while current = args.shift
|
|
35
|
+
e = @graph.add_edges(last, current)
|
|
36
|
+
last = current
|
|
37
|
+
end
|
|
38
|
+
return e
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Add a subgraph
|
|
42
|
+
def subgraph(name, &block)
|
|
43
|
+
@graph.add_graph(GraphViz::DSL.new(name, { :parent => @graph, :type => @graph.type }, &block).graph)
|
|
44
|
+
end
|
|
45
|
+
alias :cluster :subgraph
|
|
46
|
+
|
|
47
|
+
# Generate output
|
|
48
|
+
def output(options = {})
|
|
49
|
+
@graph.output(options)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Create a new undirected graph
|
|
54
|
+
def graph(name, options = {}, &block)
|
|
55
|
+
GraphViz::DSL.new(name, options.merge( { :type => "graph" } ), &block).graph
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Create a new directed graph
|
|
59
|
+
def digraph(name, options = {}, &block)
|
|
60
|
+
GraphViz::DSL.new(name, options.merge( { :type => "digraph" } ), &block).graph
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Create a new strict directed graph
|
|
64
|
+
def strict(name, options = {}, &block)
|
|
65
|
+
GraphViz::DSL.new(name, options.merge( { :type => "strict digraph" } ), &block).graph
|
|
66
|
+
end
|
|
67
|
+
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# Copyright (C) 2004 - 2012 Gregoire Lejeune <gregoire.lejeune@free.fr>
|
|
2
|
+
#
|
|
3
|
+
# This program is free software; you can redistribute it and/or modify
|
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
|
5
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
6
|
+
# (at your option) any later version.
|
|
7
|
+
#
|
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11
|
+
# GNU General Public License for more details.
|
|
12
|
+
#
|
|
13
|
+
# You should have received a copy of the GNU General Public License
|
|
14
|
+
# along with this program; if not, write to the Free Software
|
|
15
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
16
|
+
|
|
17
|
+
require 'graphviz/attrs'
|
|
18
|
+
require 'graphviz/constants'
|
|
19
|
+
|
|
20
|
+
class GraphViz
|
|
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 )
|
|
48
|
+
if not(@node_one_port and with_port)
|
|
49
|
+
GraphViz.escape(@node_one_id)
|
|
50
|
+
else
|
|
51
|
+
GraphViz.escape(@node_one_id, :force => true) + ":#{@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 )
|
|
58
|
+
if not(@node_two_port and with_port)
|
|
59
|
+
GraphViz.escape(@node_two_id)
|
|
60
|
+
else
|
|
61
|
+
GraphViz.escape(@node_two_id, :force => true) + ":#{@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
|
+
xOut = self.node_one + xLink + self.node_two
|
|
166
|
+
xAttr = ""
|
|
167
|
+
xSeparator = ""
|
|
168
|
+
@edge_attributes.data.each do |k, v|
|
|
169
|
+
xAttr << xSeparator + k + " = " + v.to_gv
|
|
170
|
+
xSeparator = ", "
|
|
171
|
+
end
|
|
172
|
+
if xAttr.length > 0
|
|
173
|
+
xOut << " [" + xAttr + "]"
|
|
174
|
+
end
|
|
175
|
+
xOut << ";"
|
|
176
|
+
|
|
177
|
+
return( xOut )
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
private
|
|
181
|
+
def getNodeNameAndPort( node )
|
|
182
|
+
name, port = nil, nil
|
|
183
|
+
if node.class == Hash
|
|
184
|
+
node.each do |k, v|
|
|
185
|
+
name, port = getNodeNameAndPort(k)
|
|
186
|
+
port = v
|
|
187
|
+
end
|
|
188
|
+
elsif node.class == String
|
|
189
|
+
name = node
|
|
190
|
+
else
|
|
191
|
+
name = node.id
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
return name, port
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
class GraphViz
|
|
2
|
+
class Elements
|
|
3
|
+
def initialize
|
|
4
|
+
@elements = Array.new
|
|
5
|
+
@elements_hash_by_type = Hash.new
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def push( obj )
|
|
9
|
+
@elements.push( obj )
|
|
10
|
+
if @elements_hash_by_type[obj['type']].nil?
|
|
11
|
+
@elements_hash_by_type[obj['type']] = Array.new
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
@elements_hash_by_type[obj['type']].push( obj )
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def each( &b )
|
|
18
|
+
@elements.each do |e|
|
|
19
|
+
yield( e )
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def size_of( type )
|
|
24
|
+
if @elements_hash_by_type[type].nil?
|
|
25
|
+
return 0
|
|
26
|
+
else
|
|
27
|
+
return @elements_hash_by_type[type].size
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def []( index, type = nil )
|
|
32
|
+
if type.nil?
|
|
33
|
+
return @elements[index]
|
|
34
|
+
else
|
|
35
|
+
return @elements_hash_by_type[type][index]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
data/lib/graphviz/ext.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'find'
|
|
2
|
+
|
|
3
|
+
class GraphViz
|
|
4
|
+
class Ext
|
|
5
|
+
def self.find( ext = nil )
|
|
6
|
+
myPath = File.join( File.dirname( File.expand_path( __FILE__ ) ), "..", "ext" )
|
|
7
|
+
found = myPath
|
|
8
|
+
unless ext.nil?
|
|
9
|
+
Find.find(myPath) do |path|
|
|
10
|
+
found = path if File.basename( path ) == ext
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
File.expand_path( found )
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
class GraphViz
|
|
2
|
+
class FamilyTree
|
|
3
|
+
class Couple
|
|
4
|
+
def initialize( graph, node, persons ) #:nodoc:
|
|
5
|
+
@graph = graph
|
|
6
|
+
@node = node
|
|
7
|
+
@kids = []
|
|
8
|
+
@persons = persons
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def node #:nodoc:
|
|
12
|
+
@node
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Add kids to a couple
|
|
16
|
+
def kids( *z )
|
|
17
|
+
@kids = GraphViz::FamilyTree::Sibling.new( z, @persons )
|
|
18
|
+
|
|
19
|
+
return
|
|
20
|
+
|
|
21
|
+
if z.size == 1
|
|
22
|
+
@graph.add_edges( @node, z[0].node, "dir" => "none" )
|
|
23
|
+
else
|
|
24
|
+
cluster = @graph.add_graph( "#{@node.id}Kids" )
|
|
25
|
+
cluster["rank"] = "same"
|
|
26
|
+
|
|
27
|
+
last = nil
|
|
28
|
+
count = 0
|
|
29
|
+
add = (z.size-1)%2 * z.size/2 + (z.size-1)%2
|
|
30
|
+
link = (z.size/2)+1
|
|
31
|
+
|
|
32
|
+
z.each do |person|
|
|
33
|
+
count = count + 1
|
|
34
|
+
if count == add
|
|
35
|
+
middle = cluster.add_nodes( "#{@node.id}Kids", "shape" => "point" )
|
|
36
|
+
@graph.add_edges( @node, middle, "dir" => "none" )
|
|
37
|
+
unless last.nil?
|
|
38
|
+
cluster.add_edges( last, middle, "dir" => "none" )
|
|
39
|
+
end
|
|
40
|
+
last = middle
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
kid = cluster.add_nodes( "#{person.node.id}Kid", "shape" => "point" )
|
|
44
|
+
@graph.add_edges( kid, person.node, "dir" => "none" )
|
|
45
|
+
|
|
46
|
+
if add == 0 and count == link
|
|
47
|
+
@graph.add_edges( @node, kid, "dir" => "none" )
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
unless last.nil?
|
|
51
|
+
cluster.add_edges( last, kid, "dir" => "none" )
|
|
52
|
+
end
|
|
53
|
+
last = kid
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def getKids
|
|
59
|
+
@kids
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
class GraphViz
|
|
2
|
+
class FamilyTree
|
|
3
|
+
class Generation
|
|
4
|
+
def initialize( graph, persons, tree, gen_number ) #:nodoc:
|
|
5
|
+
@graph = graph
|
|
6
|
+
@all_persons = persons
|
|
7
|
+
@persons = {}
|
|
8
|
+
@tree = tree
|
|
9
|
+
@gen_number = gen_number
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def all_persons #:nodoc:
|
|
13
|
+
@all_persons
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def persons
|
|
17
|
+
@persons
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def make( &block ) #:nodoc:
|
|
21
|
+
instance_eval(&block) if block
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def method_missing(sym, *args, &block) #:nodoc:
|
|
25
|
+
all_persons[sym.to_s] ||= (persons[sym.to_s] ||= GraphViz::FamilyTree::Person.new( @graph, @tree, self, sym.to_s ))
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Generation number
|
|
29
|
+
def number
|
|
30
|
+
@gen_number
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Generation size
|
|
34
|
+
def size
|
|
35
|
+
@persons.size
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'graphviz'
|
|
3
|
+
|
|
4
|
+
class GraphViz
|
|
5
|
+
class FamilyTree
|
|
6
|
+
class Person
|
|
7
|
+
def initialize( graph, tree, generation, id ) #:nodoc:
|
|
8
|
+
@graph = graph
|
|
9
|
+
@node = @graph.add_nodes( id )
|
|
10
|
+
@node["shape"] = "box"
|
|
11
|
+
@tree = tree
|
|
12
|
+
@generation = generation
|
|
13
|
+
@x, @y = 0, 0
|
|
14
|
+
@sibling = nil
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def id
|
|
18
|
+
@node.id
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def name
|
|
22
|
+
@node.label || @node.id
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def sibling
|
|
26
|
+
@sibling
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def sibling=(x)
|
|
30
|
+
@sibling=x
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def couples #:nodoc:
|
|
34
|
+
@couples
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def node #:nodoc:
|
|
38
|
+
@node
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Define the current person as a man
|
|
42
|
+
#
|
|
43
|
+
# greg.is_a_man( "Greg" )
|
|
44
|
+
def is_a_man( name )
|
|
45
|
+
@node["label"] = name
|
|
46
|
+
@node["color"] = "blue"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Define the current person as a boy
|
|
50
|
+
#
|
|
51
|
+
# greg.is_a_boy( "Greg" )
|
|
52
|
+
def is_a_boy( name )
|
|
53
|
+
is_a_man( name )
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Define the current perdon as a woman
|
|
57
|
+
#
|
|
58
|
+
# mu.is_a_woman( "Muriel" )
|
|
59
|
+
def is_a_woman( name )
|
|
60
|
+
@node["label"] = name
|
|
61
|
+
@node["color"] = "pink"
|
|
62
|
+
end
|
|
63
|
+
# Define the current perdon as a girl
|
|
64
|
+
#
|
|
65
|
+
# maia.is_a_girl( "Maia" )
|
|
66
|
+
def is_a_girl( name )
|
|
67
|
+
is_a_woman( name )
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Define that's two persons are maried
|
|
71
|
+
#
|
|
72
|
+
# mu.is_maried_with greg
|
|
73
|
+
def is_maried_with( x )
|
|
74
|
+
node = @graph.add_nodes( "#{@node.id}And#{x.node.id}" )
|
|
75
|
+
node["shape"] = "point"
|
|
76
|
+
@graph.add_edges( @node, node, "dir" => "none" )
|
|
77
|
+
@graph.add_edges( node, x.node, "dir" => "none" )
|
|
78
|
+
@tree.add_couple( self, x, node )
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Define that's two persons are divorced
|
|
82
|
+
#
|
|
83
|
+
# sophie.is_divorced_with john
|
|
84
|
+
def is_divorced_with( x )
|
|
85
|
+
node = @graph.add_nodes( "#{@node.id}And#{x.node.id}" )
|
|
86
|
+
node["shape"] = "point"
|
|
87
|
+
node["color"] = "red"
|
|
88
|
+
@graph.add_edges( @node, node, "dir" => "none", "color" => "red" )
|
|
89
|
+
@graph.add_edges( node, x.node, "dir" => "none", "color" => "red" )
|
|
90
|
+
@tree.add_couple( self, x, node )
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Define that's a person is widower of another
|
|
94
|
+
#
|
|
95
|
+
# simon.is_widower_of elisa
|
|
96
|
+
def is_widower_of( x ) #veuf
|
|
97
|
+
node = @graph.add_nodes( "#{@node.id}And#{x.node.id}" )
|
|
98
|
+
node["shape"] = "point"
|
|
99
|
+
node["color"] = "green"
|
|
100
|
+
@graph.add_edges( @node, node, "dir" => "none", "color" => "green" )
|
|
101
|
+
@graph.add_edges( node, x.node, "dir" => "none", "color" => "green" )
|
|
102
|
+
@tree.add_couple( self, x, node )
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Define the current person as dead
|
|
106
|
+
#
|
|
107
|
+
# jack.is_dead
|
|
108
|
+
def is_dead
|
|
109
|
+
@node["style"] = "filled"
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Define the kids of a single person
|
|
113
|
+
#
|
|
114
|
+
# alice.kids( john, jack, julie )
|
|
115
|
+
def kids( *z )
|
|
116
|
+
GraphViz::FamilyTree::Couple.new( @graph, @node, [self] ).kids( *z )
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|