Class: Rubyvis::Layout::Arc

Inherits:
Network show all
Defined in:
lib/rubyvis/layout/arc.rb

Overview

Implements a layout for arc diagrams. An arc diagram is a network visualization with a one-dimensional layout of nodes, using circular arcs to render links between nodes. For undirected networks, arcs are rendering on a single side; this makes arc diagrams useful as annotations to other two-dimensional network layouts, such as rollup, matrix or table layouts. For directed networks, links in opposite directions can be rendered on opposite sides using directed(true).

<p>Arc layouts are particularly sensitive to node ordering; for best results, order the nodes such that related nodes are close to each other. A poor (e.g., random) order may result in large arcs with crossovers that impede visual processing. A future improvement to this layout may include automatic reordering using, e.g., spectral graph layout or simulated annealing.

This visualization technique is related to that developed by M. Wattenberg, Arc Diagrams: Visualizing Structure in Strings in IEEE InfoVis, 2002. However, this implementation is limited to simple node-link networks, as opposed to structures with hierarchical self-similarity (such as strings). As with other network layouts, three mark prototypes are provided:<ul>

<li>node - for rendering nodes; typically a Rubyvis::Dot <li>link - for rendering links; typically a Rubyvis::Line <li>node_label - for rendering node labels; typically a Rubyvis::Label

</ul> For more details on how this layout is structured and can be customized, see Rubyvis::Layout::Network

Instance Attribute Summary collapse

Attributes inherited from Network

#_id, #link, #node, #node_label

Attributes inherited from Panel

#_canvas, #children, #root

Attributes inherited from Mark

#_properties, #binds, #child_index, #parent, #proto, #root, #scale, #scene, #target

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Network

#_link, #_node, #_node_label, #build_properties, #network_build_implied, #nodes, #reset

Methods inherited from Rubyvis::Layout

Arc, Cluster, Grid, Hierarchy, Horizon, Indent, Matrix, Network, Pack, Partition, Stack, Tree, Treemap, attr_accessor_dsl, #build_properties, #layout_build_implied, #layout_build_properties

Methods inherited from Panel

#add, #anchor, #bind, #build_instance, #children_inspect, #panel_build_implied, #to_svg, #type

Methods inherited from Bar

#type, #width

Methods inherited from Mark

#add, #anchor, #area, attr_accessor_dsl, #bar, #bind, #build, #build_instance, #build_properties, #context, #context_apply, #context_clear, #cousin, #delete_index, #dot, #event, #execute, #first, #image, index, #index, index=, #index=, #index_defined?, #instance, #instances, #label, #last, #layout_arc, #layout_cluster, #layout_grid, #layout_horizon, #layout_indent, #layout_matrix, #layout_pack, #layout_partition, #layout_partition_fill, #layout_stack, #layout_tree, #layout_treemap, #line, #margin, #mark_anchor, #mark_bind, #mark_build_implied, #mark_build_instance, #mark_build_properties, #mark_extend, mark_method, #panel, #properties, properties, property_method, #property_value, #render, #rule, scene, scene=, #sibling, stack, stack=, #type, #wedge

Constructor Details

#initializeArc

Returns a new instance of Arc.



40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/rubyvis/layout/arc.rb', line 40

def initialize
  super
  @_interpolate=nil # cached interpolate
  @_directed=nil # cached directed
  @_reverse=nil # cached reverse
  @_sort=nil
  that=self
  @link.data(lambda {|_p|
      s=_p.source_node;t=_p.target_node
      that._reverse != (that._directed or (s.breadth < t.breadth)) ? [s, t] : [t, s]
  }).interpolate(lambda{ that._interpolate})
end

Instance Attribute Details

#_directedObject

:nodoc:



38
39
40
# File 'lib/rubyvis/layout/arc.rb', line 38

def _directed
  @_directed
end

#_interpolateObject

:nodoc:



37
38
39
# File 'lib/rubyvis/layout/arc.rb', line 37

def _interpolate
  @_interpolate
end

#_reverseObject

:nodoc:



39
40
41
# File 'lib/rubyvis/layout/arc.rb', line 39

def _reverse
  @_reverse
end

Class Method Details

.defaultsObject

Default properties for arc layouts. By default, the orientation is “bottom”.



157
158
159
160
# File 'lib/rubyvis/layout/arc.rb', line 157

def self.defaults
  Arc.new.mark_extend(Network.defaults).
    orient("bottom")
end

Instance Method Details

#build_implied(s) ⇒ Object

:nodoc:



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/rubyvis/layout/arc.rb', line 53

def build_implied(s) # :nodoc:
  return true if network_build_implied(s)
  # Cached
  
  nodes = s.nodes
  orient = s.orient
  sort = @_sort
  index = Rubyvis.range(nodes.size)
  w = s.width
  h = s.height
  r = [w,h].min / 2.0 
  # /* Sort the nodes. */
  if (sort)
    index.sort! {|a,b| sort.call(nodes[a],nodes[b])}
  end
  
  
  
  #/** @private Returns the mid-angle, given the breadth. */
  mid_angle=lambda do |b| 
    case orient 
      when "top"
        -Math::PI / 2.0
      when "bottom"
        Math::PI / 2.0
      when "left"
        Math::PI
      when "right"
        0
      when "radial"
        (b - 0.25) * 2.0 * Math::PI
    end
  end
  
  # /** @private Returns the x-position, given the breadth. */
  x= lambda do |b|
    case orient 
      when "top"
        b * w
      when "bottom"
       b * w
      when "left"
      0;
      when "right"
      w;
      when "radial"
        w / 2.0 + r * Math.cos(mid_angle.call(b))
    end
  end
  
  # /** @private Returns the y-position, given the breadth. */
  y=lambda do |b| 
    case orient 
    when "top"
      0;
    when "bottom"
      h;
    when "left"
      b* h
    when "right"
      b * h
    when "radial"
      h / 2.0 + r * Math.sin(mid_angle.call(b))
    end
  end
  
  #/* Populate the x, y and mid-angle attributes. */
  nodes.each_with_index do |nod, i|
    n=nodes[index[i]]
    n.breadth=(i+0.5) / nodes.size
    b=n.breadth
    n.x=x[b]
    n.y=y[b]
    n.mid_angle=mid_angle[b]
  end        
  
  @_directed = s.directed
  @_interpolate = s.orient == "radial" ? "linear" : "polar"
  @_reverse = s.orient == "right" or s.orient == "top"
  
end

#orientObject

:attr: directed Whether this arc digram is directed (bidirectional); only applies to non-radial orientations. By default, arc digrams are undirected, such that all arcs appear on one side. If the arc digram is directed, then forward links are drawn on the conventional side (the same as as undirected links–right, left, bottom and top for left, right, top and bottom, respectively), while reverse links are drawn on the opposite side.



155
# File 'lib/rubyvis/layout/arc.rb', line 155

attr_accessor_dsl :orient, :directed

#sort(f = nil, &block) ⇒ Object

Specifies an optional sort function. The sort function follows the same comparator contract required by Rubyvis::Dom::Node.sort(). Specifying a sort function provides an alternative to sort the nodes as they are specified by the nodes property; the main advantage of doing this is that the comparator function can access implicit fields populated by the network layout, such as the link_degree.

<p>Note that arc diagrams are particularly sensitive to order. This is referred to as the seriation problem, and many different techniques exist to find good node orders that emphasize clusters, such as spectral layout and simulated annealing.



173
174
175
176
177
# File 'lib/rubyvis/layout/arc.rb', line 173

def sort(f=nil,&block)
  f||=block
  @_sort=f
  self
end