Class: Pacer::Utils::YFilesExport

Inherits:
Object
  • Object
show all
Defined in:
lib/pacer/utils/y_files.rb

Overview

Exports a graph to GraphML with some yworks.com graphml formatting extensions.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeYFilesExport

Returns a new instance of YFilesExport.



24
25
26
27
28
29
30
# File 'lib/pacer/utils/y_files.rb', line 24

def initialize
  self.vertex_label = proc { |v| v[:name] }
  self.edge_label = proc { |e| e.label }
  self.vertex_properties = self.edge_properties = proc { |x| x.properties }
  self.vertex_fill = proc { |v| "#FFCC00" }
  self.edge_color = proc { |e| "#000000" }
end

Instance Attribute Details

#edge_colorObject

a proc that takes an edge and returns a color in hex format: “#aaee00”



20
21
22
# File 'lib/pacer/utils/y_files.rb', line 20

def edge_color
  @edge_color
end

#edge_labelObject

a proc that takes an edge and returns a label string



18
19
20
# File 'lib/pacer/utils/y_files.rb', line 18

def edge_label
  @edge_label
end

#edge_propertiesObject

a proc that takes an edge and returns a hash of properties to be exported



22
23
24
# File 'lib/pacer/utils/y_files.rb', line 22

def edge_properties
  @edge_properties
end

#vertex_fillObject

a proc that takes a vertex and returns a color in hex format: “#aaee00”



13
14
15
# File 'lib/pacer/utils/y_files.rb', line 13

def vertex_fill
  @vertex_fill
end

#vertex_labelObject

a proc that takes a vertex and returns a label string



11
12
13
# File 'lib/pacer/utils/y_files.rb', line 11

def vertex_label
  @vertex_label
end

#vertex_propertiesObject

a proc that takes a vertex and returns a hash of properties to be exported



15
16
17
# File 'lib/pacer/utils/y_files.rb', line 15

def vertex_properties
  @vertex_properties
end

Instance Method Details

#export(route, path) ⇒ Object

Export the given graph to the given path in an extended .graphml format.



33
34
35
36
37
38
39
# File 'lib/pacer/utils/y_files.rb', line 33

def export(route, path)
  x = xml(route)
  puts "\n\nWriting XML"
  File.open(File.expand_path(path), 'w') do |f|
    f.puts x.to_xml
  end
end

#xml(route) ⇒ Object

Returns the xml builder used to construct the xml for the given graph.



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
# File 'lib/pacer/utils/y_files.rb', line 42

def xml(route)
  node_keys = Set[]
  edge_keys = Set[]
  n = 0
  builder = Nokogiri::XML::Builder.new do |xml|
    xml.graphml('xmlns' => "http://graphml.graphdrawing.org/xmlns",
                'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
                'xmlns:y' => "http://www.yworks.com/xml/graphml",
                'xsi:schemaLocation' => "http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd") do
      xml.key 'for' => "node", 'id' => "y.nodegraphics", 'yfiles.type' => "nodegraphics"
      xml.key 'attr.name' => "description", 'attr.type' => "string", 'for' => "node", 'id' => "d2"
      xml.key 'for' => "edge", 'id' => "y.edgegraphics", 'yfiles.type' => "edgegraphics"
      puts "Building XML data structure"
      puts "Vertices"
      route.paths.vertices.scatter(element_type: :vertex).uniq.each do |v|
        n += 1
        print '.' if n % 100 == 0
        xml.node :id => v.element_id do
          xml.data :key => 'y.nodegraphics' do
            xml['y'].ShapeNode do
              #xml['y'].Geometry 'height' => "30.0", 'width' => "30.0", 'x' => "15.0", 'y' => "0.0"
              xml['y'].Fill 'color' => vertex_fill.call(v), 'transparent' => "false"
              xml['y'].BorderStyle 'color' => "#000000", 'type' => "line", 'width' => "1.0"
              xml['y'].NodeLabel('alignment' => "center",
                                 'autoSizePolicy' => "content",
                                 'fontFamily' => "Dialog",
                                 'fontSize' => "12",
                                 'fontStyle' => "plain",
                                 'hasBackgroundColor' => "false",
                                 'hasLineColor' => "false",
                                 #'height' => "4.0",
                                 'modelName' => "internal",
                                 'modelPosition' => "c",
                                 'textColor' => "#000000",
                                 'visible' => "true"
                                 #'width' => "4.0",
                                 #'x' => "13.0",
                                 #'y' => "13.0"
                                ) { xml.text vertex_label.call(v) }
              xml['y'].Shape 'type' => "rectangle"
            end
          end
          vertex_properties.call(v).each do |name, value|
            node_keys << name
            xml.data(:key => name) { xml.text value }
          end
        end
      end
      puts "\n\nEdges"
      route.paths.edges.scatter(element_type: :edge).uniq.each do |e|
        n += 1
        print '.' if n % 100 == 0
        xml.edge :id => e.element_id, :source => e.out_vertex.element_id, :target => e.in_vertex.element_id, :label => e.label do
          xml.data :key => 'y.edgegraphics' do
            xml['y'].PolyLineEdge do
              xml['y'].LineStyle 'color' => edge_color.call(e), 'type' => 'line', 'width' => '1.0'
              xml['y'].Arrows 'source' => 'none', 'target' => 'standard'
              xml['y'].EdgeLabel('alignment' => "center",
                                 #'distance' => "2.0",
                                 'fontFamily' => "Dialog",
                                 'fontSize' => "12",
                                 'fontStyle' => "plain",
                                 'hasBackgroundColor' => "false",
                                 'hasLineColor' => "false",
                                 #'height' => "18.1328125",
                                 'modelName' => "side_slider",
                                 #'preferredPlacement' => "right",
                                 #'ratio' => "0.43751239324621083",
                                 'textColor' => "#000000",
                                 'visible' => "true"
                                 #'width' => "28.87890625",
                                 #'x' => "49.62109375",
                                 #'y' => "-27.201349990172957"
                                ) { xml.text edge_label.call(e) }
            end
          end
          edge_properties.call(e).each do |name, value|
            edge_keys << name
            xml.data(:key => name) { xml.text value }
          end
        end
      end

      node_keys.each do |key|
        xml.key :id => key, :for => 'node', 'attr.name' => key, 'attr.type' => 'string'
      end
      edge_keys.each do |key|
        xml.key :id => key, :for => 'edge', 'attr.name' => key, 'attr.type' => 'string'
      end
    end
  end
end