Class: Graphdown::Graph
- Inherits:
-
Object
- Object
- Graphdown::Graph
- Defined in:
- lib/graphdown/graph.rb
Constant Summary collapse
- PADDING =
10
Instance Attribute Summary collapse
-
#nodes ⇒ Object
readonly
Returns the value of attribute nodes.
Instance Method Summary collapse
- #<<(node) ⇒ Object
- #find_node_by_label(label) ⇒ Object
-
#initialize ⇒ Graph
constructor
A new instance of Graph.
- #layer_nodes ⇒ Object
- #layered_nodes ⇒ Object
- #layout_edges ⇒ Object
- #layout_nodes ⇒ Object
- #to_svg ⇒ Object
Constructor Details
#initialize ⇒ Graph
Returns a new instance of Graph.
9 10 11 12 13 |
# File 'lib/graphdown/graph.rb', line 9 def initialize @nodes = [] @width = 0 @height = 0 end |
Instance Attribute Details
#nodes ⇒ Object (readonly)
Returns the value of attribute nodes.
5 6 7 |
# File 'lib/graphdown/graph.rb', line 5 def nodes @nodes end |
Instance Method Details
#<<(node) ⇒ Object
15 16 17 18 |
# File 'lib/graphdown/graph.rb', line 15 def <<(node) labels = @nodes.map(&:label) @nodes << node unless labels.include?(node.label) end |
#find_node_by_label(label) ⇒ Object
20 21 22 |
# File 'lib/graphdown/graph.rb', line 20 def find_node_by_label(label) (@nodes || []).select { |node| node.label == label }.first end |
#layer_nodes ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/graphdown/graph.rb', line 28 def layer_nodes nodes_with_level = @nodes.select { |node| node.level >= 1 } begin diff_total = 0 nodes_with_level.each do |node| node.children.each do |child| if node.level >= child.level child.level += node.level + 1 diff_total += node.level + 1 end end end end while diff_total != 0 end |
#layered_nodes ⇒ Object
24 25 26 |
# File 'lib/graphdown/graph.rb', line 24 def layered_nodes @layered_nodes ||= @nodes.sort_by(&:level).group_by(&:level).values end |
#layout_edges ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/graphdown/graph.rb', line 60 def layout_edges @nodes.each do |node| node.child_edges.each_with_index do |edge, index| edge.origin.x = node.x + (node.width.to_f * (index + 1) / (node.child_edges.count + 1)) edge.origin.y = node.y + node.height end node.parent_edges.each_with_index do |edge, index| edge.target.x = node.x + (node.width.to_f * (index + 1) / (node.parent_edges.count + 1)) edge.target.y = node.y end end end |
#layout_nodes ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/graphdown/graph.rb', line 43 def layout_nodes layer_widths = [] layer_offset = PADDING layered_nodes.each do |nodes| node_offset = PADDING nodes.each do |node| node.x = node_offset node.y = layer_offset node_offset += node.width + Node::MARGIN_RIGHT end layer_widths << node_offset + PADDING layer_offset += nodes.map(&:height).max + Node::MARGIN_BOTTOM end @width = layer_widths.max @height = layer_offset + PADDING end |
#to_svg ⇒ Object
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 |
# File 'lib/graphdown/graph.rb', line 74 def to_svg svg = SVGen::SVG.new(width: @width, height: @height) do |svg| # nodes svg.g(fill: "none", stroke: "black") do |g| @nodes.each do |node| g.rect(x: node.x, y: node.y, width: node.width, height: node.height) end end # texts svg.g("font-size" => Node::FONT_SIZE, "font-family" => Node::FONT_FAMILY, "text-anchor" => "middle") do |g| @nodes.each do |node| g.text(node.label, x: node.x + node.width / 2, y: node.y + Node::WORD_HEIGHT + Node::PADDING_TOP / 2) end end # edges svg.g(stroke: "black", "stroke-width" => 2) do |g| @nodes.each do |node| node.child_edges.each do |edge| g.path(d: edge.line_d, fill: "none") g.path(d: edge.arrow_d, fill: "black") if edge.forward? g.path(d: edge.reverse_arrow_d, fill: "black") if edge.backward? end end end end svg.generate end |