rubyvis 0.1.7 → 0.2.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.
- data.tar.gz.sig +0 -0
- data/History.txt +12 -0
- data/Manifest.txt +9 -2
- data/README.txt +30 -59
- data/examples/area_interpolation.rb +56 -0
- data/examples/{first.rb → first_protovis_api.rb} +1 -1
- data/examples/first_rbp_api.rb +21 -0
- data/examples/image.rb +0 -1
- data/examples/line.rb +0 -1
- data/examples/line_interpolation.rb +55 -0
- data/lib/rubyvis.rb +3 -3
- data/lib/rubyvis/color/color.rb +177 -20
- data/lib/rubyvis/color/colors.rb +98 -0
- data/lib/rubyvis/layout/stack.rb +271 -196
- data/lib/rubyvis/mark.rb +26 -9
- data/lib/rubyvis/mark/anchor.rb +2 -1
- data/lib/rubyvis/mark/area.rb +99 -1
- data/lib/rubyvis/mark/bar.rb +2 -2
- data/lib/rubyvis/mark/dot.rb +2 -2
- data/lib/rubyvis/mark/line.rb +116 -4
- data/lib/rubyvis/mark/panel.rb +2 -1
- data/lib/rubyvis/mark/shorcut_methods.rb +58 -0
- data/lib/rubyvis/scale/quantitative.rb +5 -3
- data/lib/rubyvis/scene/svg_area.rb +127 -121
- data/lib/rubyvis/scene/svg_curve.rb +328 -0
- data/lib/rubyvis/scene/svg_line.rb +20 -18
- data/lib/rubyvis/scene/svg_scene.rb +5 -4
- data/lib/rubyvis/sceneelement.rb +4 -1
- data/spec/area_spec.rb +48 -0
- data/spec/bar_spec.rb +1 -1
- data/spec/line_spec.rb +63 -0
- data/spec/panel_spec.rb +2 -4
- data/spec/ruby_api_spec.rb +47 -0
- data/spec/scale_linear_spec.rb +14 -1
- data/spec/spec_helper.rb +35 -0
- data/web/Rakefile +1 -1
- data/web/build_site.rb +17 -1
- data/web/examples.haml +2 -2
- data/web/index.haml +13 -7
- metadata +16 -6
- metadata.gz.sig +0 -0
- data/lib/rubyvis/color/ramp.rb +0 -1
data/lib/rubyvis/color/colors.rb
CHANGED
@@ -1,14 +1,61 @@
|
|
1
1
|
module Rubyvis
|
2
|
+
#
|
3
|
+
# :section: colors/Ramp.js
|
4
|
+
|
5
|
+
|
6
|
+
# Returns a linear color ramp from the specified <tt>start</tt> color to the
|
7
|
+
# specified <tt>end</tt> color. The color arguments may be specified either as
|
8
|
+
# <tt>string</tt>s or as Rubyvis::Color. This is equivalent to:
|
9
|
+
#
|
10
|
+
# <pre> pv.Scale.linear().domain(0, 1).range(...)</pre>
|
11
|
+
def self.ramp(*arguments)
|
12
|
+
start, _end, dummy = arguments
|
13
|
+
scale = Rubyvis.Scale.linear
|
14
|
+
scale.range(*arguments)
|
15
|
+
scale
|
16
|
+
end
|
17
|
+
|
18
|
+
# :section: colors/Colors.js
|
19
|
+
|
2
20
|
# Alias for Rubyvis::Colors
|
3
21
|
def self.Colors
|
4
22
|
Rubyvis::Colors
|
5
23
|
end
|
24
|
+
|
25
|
+
# Returns a new categorical color encoding using the specified colors. The
|
26
|
+
# arguments to this method are an array of colors; see Rubyvis.color(). For
|
27
|
+
# example, to create a categorical color encoding using the <tt>species</tt>
|
28
|
+
# attribute:
|
29
|
+
#
|
30
|
+
# <pre>Rubyvis.colors("red", "green", "blue").by(lambda{|d| d.species})</pre>
|
31
|
+
#
|
32
|
+
# The result of this expression can be used as a fill- or stroke-style
|
33
|
+
# property. This assumes that the data's <tt>species</tt> attribute is a
|
34
|
+
# string.
|
35
|
+
#
|
6
36
|
def self.colors(*args)
|
7
37
|
scale=Rubyvis::Scale.ordinal
|
8
38
|
scale.range(*args)
|
9
39
|
scale
|
10
40
|
end
|
41
|
+
|
42
|
+
# A collection of standard color palettes for categorical encoding.
|
11
43
|
module Colors
|
44
|
+
|
45
|
+
# Returns a new 10-color scheme. The arguments to this constructor are
|
46
|
+
# optional, and equivalent to calling Rubyvis::Scale::Ordinal.domain. The
|
47
|
+
# following colors are used:
|
48
|
+
#
|
49
|
+
# <div style="background:#1f77b4;">#1f77b4</div>
|
50
|
+
# <div style="background:#ff7f0e;">#ff7f0e</div>
|
51
|
+
# <div style="background:#2ca02c;">#2ca02c</div>
|
52
|
+
# <div style="background:#d62728;">#d62728</div>
|
53
|
+
# <div style="background:#9467bd;">#9467bd</div>
|
54
|
+
# <div style="background:#8c564b;">#8c564b</div>
|
55
|
+
# <div style="background:#e377c2;">#e377c2</div>
|
56
|
+
# <div style="background:#7f7f7f;">#7f7f7f</div>
|
57
|
+
# <div style="background:#bcbd22;">#bcbd22</div>
|
58
|
+
# <div style="background:#17becf;">#17becf</div>
|
12
59
|
def self.category10(*arguments)
|
13
60
|
scale = Rubyvis.colors(
|
14
61
|
"#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd",
|
@@ -16,6 +63,30 @@ module Rubyvis
|
|
16
63
|
scale.domain(*arguments) if arguments.size>0
|
17
64
|
scale
|
18
65
|
end
|
66
|
+
|
67
|
+
# Returns a new alternative 19-color scheme. The arguments to this constructor
|
68
|
+
# are optional, and equivalent to calling
|
69
|
+
# Rubyvis::Scale::Ordinal.domain. The following colors are used:
|
70
|
+
#
|
71
|
+
# <div style="background:#9c9ede;">#9c9ede</div>
|
72
|
+
# <div style="background:#7375b5;">#7375b5</div>
|
73
|
+
# <div style="background:#4a5584;">#4a5584</div>
|
74
|
+
# <div style="background:#cedb9c;">#cedb9c</div>
|
75
|
+
# <div style="background:#b5cf6b;">#b5cf6b</div>
|
76
|
+
# <div style="background:#8ca252;">#8ca252</div>
|
77
|
+
# <div style="background:#637939;">#637939</div>
|
78
|
+
# <div style="background:#e7cb94;">#e7cb94</div>
|
79
|
+
# <div style="background:#e7ba52;">#e7ba52</div>
|
80
|
+
# <div style="background:#bd9e39;">#bd9e39</div>
|
81
|
+
# <div style="background:#8c6d31;">#8c6d31</div>
|
82
|
+
# <div style="background:#e7969c;">#e7969c</div>
|
83
|
+
# <div style="background:#d6616b;">#d6616b</div>
|
84
|
+
# <div style="background:#ad494a;">#ad494a</div>
|
85
|
+
# <div style="background:#843c39;">#843c39</div>
|
86
|
+
# <div style="background:#de9ed6;">#de9ed6</div>
|
87
|
+
# <div style="background:#ce6dbd;">#ce6dbd</div>
|
88
|
+
# <div style="background:#a55194;">#a55194</div>
|
89
|
+
# <div style="background:#7b4173;">#7b4173</div>
|
19
90
|
def self.category19(*arguments)
|
20
91
|
scale = Rubyvis.colors(
|
21
92
|
"#9c9ede", "#7375b5", "#4a5584", "#cedb9c", "#b5cf6b",
|
@@ -25,6 +96,33 @@ module Rubyvis
|
|
25
96
|
scale.domain(*arguments) if arguments.size>0
|
26
97
|
scale
|
27
98
|
end
|
99
|
+
|
100
|
+
|
101
|
+
# Returns a new 20-color scheme. The arguments to this constructor are
|
102
|
+
# optional, and equivalent to calling Rubyvis::Scale::Ordinal.domain. The
|
103
|
+
# following colors are used:
|
104
|
+
#
|
105
|
+
# <div style="background:#1f77b4;">#1f77b4</div>
|
106
|
+
# <div style="background:#aec7e8;">#aec7e8</div>
|
107
|
+
# <div style="background:#ff7f0e;">#ff7f0e</div>
|
108
|
+
# <div style="background:#ffbb78;">#ffbb78</div>
|
109
|
+
# <div style="background:#2ca02c;">#2ca02c</div>
|
110
|
+
# <div style="background:#98df8a;">#98df8a</div>
|
111
|
+
# <div style="background:#d62728;">#d62728</div>
|
112
|
+
# <div style="background:#ff9896;">#ff9896</div>
|
113
|
+
# <div style="background:#9467bd;">#9467bd</div>
|
114
|
+
# <div style="background:#c5b0d5;">#c5b0d5</div>
|
115
|
+
# <div style="background:#8c564b;">#8c564b</div>
|
116
|
+
# <div style="background:#c49c94;">#c49c94</div>
|
117
|
+
# <div style="background:#e377c2;">#e377c2</div>
|
118
|
+
# <div style="background:#f7b6d2;">#f7b6d2</div>
|
119
|
+
# <div style="background:#7f7f7f;">#7f7f7f</div>
|
120
|
+
# <div style="background:#c7c7c7;">#c7c7c7</div>
|
121
|
+
# <div style="background:#bcbd22;">#bcbd22</div>
|
122
|
+
# <div style="background:#dbdb8d;">#dbdb8d</div>
|
123
|
+
# <div style="background:#17becf;">#17becf</div>
|
124
|
+
# <div style="background:#9edae5;">#9edae5</div>
|
125
|
+
|
28
126
|
def self.category20(*arguments)
|
29
127
|
scale = Rubyvis.colors(
|
30
128
|
"#1f77b4", "#aec7e8", "#ff7f0e", "#ffbb78", "#2ca02c",
|
data/lib/rubyvis/layout/stack.rb
CHANGED
@@ -1,225 +1,300 @@
|
|
1
1
|
module Rubyvis
|
2
2
|
class Layout
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
class Stack < Rubyvis::Layout
|
7
|
-
@properties=Panel.properties.dup
|
8
|
-
|
9
|
-
attr_accessor :_x, :_y, :_values, :prop
|
10
|
-
attr_accessor_dsl :orient,:offset, :order, :layers
|
11
|
-
def self.defaults
|
12
|
-
Stack.new.extend(Layout.defaults).orient("bottom-left").offset("zero").layers([[]])
|
13
|
-
end
|
14
|
-
def initialize
|
15
|
-
super
|
16
|
-
@none=lambda {nil}
|
17
|
-
@prop = {"t"=> @none, "l"=> @none, "r"=> @none, "b"=> @none, "w"=> @none, "h"=> @none}
|
18
|
-
@values=nil
|
19
|
-
@_x=lambda {return 0}
|
20
|
-
@_y=lambda {return 0}
|
21
|
-
@_values=Rubyvis.identity
|
22
|
-
end
|
23
|
-
def x(f)
|
24
|
-
@_x=Rubyvis.functor(f)
|
25
|
-
return self
|
26
|
-
end
|
27
|
-
def y(f)
|
28
|
-
@_y=Rubyvis.functor(f)
|
29
|
-
return self
|
3
|
+
# Alias for Rubyvis::Layout::Stack
|
4
|
+
def self.Stack
|
5
|
+
Rubyvis::Layout::Stack
|
30
6
|
end
|
31
|
-
def values(f=nil)
|
32
|
-
if f.nil?
|
33
|
-
@values
|
34
|
-
else
|
35
|
-
@_values=Rubyvis.functor(f)
|
36
|
-
return self
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
7
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
8
|
+
# Implements a layout for stacked visualizations, ranging from simple
|
9
|
+
# stacked bar charts to more elaborate "streamgraphs" composed of stacked
|
10
|
+
# areas. Stack layouts uses length as a visual encoding, as opposed to
|
11
|
+
# position, as the layers do not share an aligned axis.
|
12
|
+
#
|
13
|
+
# <p>Marks can be stacked vertically or horizontally. For example,
|
14
|
+
#
|
15
|
+
# vis.add(Rubyvis::Layout::Stack)
|
16
|
+
# .layers([[1, 1.2, 1.7, 1.5, 1.7],
|
17
|
+
# [.5, 1, .8, 1.1, 1.3],
|
18
|
+
# [.2, .5, .8, .9, 1]])
|
19
|
+
# .x(lambda { index * 35})
|
20
|
+
# .y(lambda {|d| d * 40})
|
21
|
+
# .layer.add(Rubyvis::Area)
|
22
|
+
#
|
23
|
+
# specifies a vertically-stacked area chart, using the default "bottom-left"
|
24
|
+
# orientation with "zero" offset. This visualization can be easily changed into
|
25
|
+
# a streamgraph using the "wiggle" offset, which attempts to minimize change in
|
26
|
+
# slope weighted by layer thickness. See the offset property for more
|
27
|
+
# supported streamgraph algorithms.
|
28
|
+
#
|
29
|
+
# <p>In the simplest case, the layer data can be specified as a two-dimensional
|
30
|
+
# array of numbers. The <tt>x</tt> and <tt>y</tt> psuedo-properties are used to
|
31
|
+
# define the thickness of each layer at the given position, respectively; in
|
32
|
+
# the above example of the "bottom-left" orientation, the <tt>x</tt> and
|
33
|
+
# <tt>y</tt> psuedo-properties are equivalent to the <tt>left</tt> and
|
34
|
+
# <tt>height</tt> properties that you might use if you implemented a stacked
|
35
|
+
# area by hand.
|
36
|
+
#
|
37
|
+
# <p>The advantage of using the stack layout is that the baseline, i.e., the
|
38
|
+
# <tt>bottom</tt> property is computed automatically using the specified offset
|
39
|
+
# algorithm. In addition, the order of layers can be computed using a built-in
|
40
|
+
# algorithm via the <tt>order</tt> property.
|
41
|
+
#
|
42
|
+
# <p>With the exception of the "expand" <tt>offset</tt>, the stack layout does
|
43
|
+
# not perform any automatic scaling of data; the values returned from
|
44
|
+
# <tt>x</tt> and <tt>y</tt> specify pixel sizes. To simplify scaling math, use
|
45
|
+
# this layout in conjunction with Rubyvis::Scale.linea} or similar.
|
46
|
+
#
|
47
|
+
# <p>In other cases, the <tt>values</tt> psuedo-property can be used to define
|
48
|
+
# the data more flexibly. As with a typical panel & area, the
|
49
|
+
# <tt>layers</tt> property corresponds to the data in the enclosing panel,
|
50
|
+
# while the <tt>values</tt> psuedo-property corresponds to the data for the
|
51
|
+
# area within the panel. For example, given an array of data values:
|
52
|
+
#
|
53
|
+
# crimea = [
|
54
|
+
# { date: "4/1854", wounds: 0, other: 110, disease: 110 },
|
55
|
+
# { date: "5/1854", wounds: 0, other: 95, disease: 105 },
|
56
|
+
# { date: "6/1854", wounds: 0, other: 40, disease: 95 },
|
57
|
+
# ...
|
58
|
+
#
|
59
|
+
# and a corresponding array of series names:
|
60
|
+
#
|
61
|
+
# causes = [:wounds, :other, :disease]
|
62
|
+
#
|
63
|
+
# Separate layers can be defined for each cause like so:
|
64
|
+
#
|
65
|
+
# vis.add(pv.Layout.Stack)
|
66
|
+
# .layers(causes)
|
67
|
+
# .values(crimea)
|
68
|
+
# .x(lambda {|d| x.scale(d[:date]})
|
69
|
+
# .y(lambda {|d,dp| y.scale(d[dp])})
|
70
|
+
# .layer.add(pv.Area)
|
71
|
+
#
|
72
|
+
# As with the panel & area case, the datum that is passed to the
|
73
|
+
# psuedo-properties <tt>x</tt> and <tt>y</tt> are the values (an element in
|
74
|
+
# <tt>crimea</tt>); the second argument is the layer data (a string in
|
75
|
+
# <tt>causes</tt>). Additional arguments specify the data of enclosing panels, if any.
|
76
|
+
class Stack < Rubyvis::Layout
|
77
|
+
@properties=Panel.properties.dup
|
78
|
+
|
79
|
+
attr_accessor :_x, :_y, :_values, :prop
|
80
|
+
attr_accessor_dsl :orient,:offset, :order, :layers
|
81
|
+
def self.defaults
|
82
|
+
Stack.new.extend(Layout.defaults).orient("bottom-left").offset("zero").layers([[]])
|
61
83
|
end
|
62
|
-
h = self.parent.send(horizontal ? "height" : "width")
|
63
|
-
x = []
|
64
|
-
y = []
|
65
|
-
dy = []
|
66
84
|
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
|
71
|
-
|
72
|
-
|
85
|
+
# Constructs a new, empty stack layout. Layouts are not typically constructed
|
86
|
+
# directly; instead, they are added to an existing panel via
|
87
|
+
# Rubyvis::Mark.add
|
88
|
+
def initialize
|
89
|
+
super
|
90
|
+
@none=lambda {nil}
|
91
|
+
@prop = {"t"=> @none, "l"=> @none, "r"=> @none, "b"=> @none, "w"=> @none, "h"=> @none}
|
92
|
+
@values=nil
|
93
|
+
@_x=lambda {return 0}
|
94
|
+
@_y=lambda {return 0}
|
95
|
+
@_values=Rubyvis.identity
|
96
|
+
end
|
97
|
+
def x(f)
|
98
|
+
@_x=Rubyvis.functor(f)
|
99
|
+
return self
|
100
|
+
end
|
101
|
+
def y(f)
|
102
|
+
@_y=Rubyvis.functor(f)
|
103
|
+
return self
|
104
|
+
end
|
105
|
+
def values(f=nil)
|
106
|
+
if f.nil?
|
107
|
+
@values
|
108
|
+
else
|
109
|
+
@_values=Rubyvis.functor(f)
|
110
|
+
return self
|
111
|
+
end
|
112
|
+
end
|
73
113
|
|
74
|
-
o = OpenStruct.new({:parent=> OpenStruct.new({:parent=> self})})
|
75
|
-
stack.unshift(nil)
|
76
|
-
values = []
|
77
|
-
n.times {|i|
|
78
|
-
dy[i] = []
|
79
|
-
y[i] = []
|
80
|
-
o.parent.index = i
|
81
|
-
stack[0] = data[i]
|
82
|
-
values[i] = self._values.js_apply(o.parent, stack);
|
83
|
-
m = values[i].size if (i==0)
|
84
|
-
stack.unshift(nil)
|
85
|
-
m.times {|j|
|
86
|
-
stack[0] = values[i][j]
|
87
|
-
o.index = j
|
88
|
-
x[j] = self._x.js_apply(o, stack) if i==0
|
89
|
-
dy[i][j] = self._y.js_apply(o, stack)
|
90
|
-
}
|
91
|
-
stack.shift()
|
92
|
-
}
|
93
|
-
stack.shift()
|
94
114
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
sums = dy.map {|v| Rubyvis.sum(v)}
|
102
|
-
top = 0
|
103
|
-
bottom = 0
|
104
|
-
tops = []
|
105
|
-
bottoms = []
|
106
|
-
n.times {|i|
|
107
|
-
j = map[i]
|
108
|
-
if (top < bottom)
|
109
|
-
top += sums[j];
|
110
|
-
tops.push(j);
|
111
|
-
else
|
112
|
-
bottom += sums[j];
|
113
|
-
bottoms.push(j);
|
114
|
-
end
|
115
|
+
def proxy(name)
|
116
|
+
that=self
|
117
|
+
return lambda {
|
118
|
+
a=that.prop[name].js_call(self, self.parent.index, self.index);
|
119
|
+
puts "proxy(#{name}): #{a}" if $DEBUG
|
120
|
+
a
|
115
121
|
}
|
116
|
-
_index = bottoms.reverse+tops
|
117
|
-
|
118
|
-
when "reverse"
|
119
|
-
_index = Rubyvis.range(n - 1, -1, -1)
|
120
|
-
else
|
121
|
-
_index = Rubyvis.range(n)
|
122
122
|
end
|
123
123
|
|
124
|
-
|
125
|
-
|
126
|
-
|
124
|
+
def build_implied(s)
|
125
|
+
# puts "Build stack" if $DEBUG
|
126
|
+
panel_build_implied(s)
|
127
|
+
data = s.layers
|
128
|
+
n = data.size
|
129
|
+
m = nil
|
130
|
+
orient = s.orient
|
131
|
+
if orient =~/^(top|bottom)\b/
|
132
|
+
horizontal=true
|
133
|
+
else
|
134
|
+
horizontal=false
|
135
|
+
end
|
136
|
+
h = self.parent.send(horizontal ? "height" : "width")
|
137
|
+
x = []
|
138
|
+
y = []
|
139
|
+
dy = []
|
140
|
+
|
141
|
+
#
|
142
|
+
# Iterate over the data, evaluating the values, x and y functions. The
|
143
|
+
# context in which the x and y psuedo-properties are evaluated is a
|
144
|
+
# pseudo-mark that is a grandchild of this layout.
|
145
|
+
#
|
146
|
+
stack = Rubyvis::Mark.stack
|
147
|
+
|
148
|
+
o = OpenStruct.new({:parent=> OpenStruct.new({:parent=> self})})
|
149
|
+
stack.unshift(nil)
|
150
|
+
values = []
|
151
|
+
n.times {|i|
|
152
|
+
dy[i] = []
|
153
|
+
y[i] = []
|
154
|
+
o.parent.index = i
|
155
|
+
stack[0] = data[i]
|
156
|
+
values[i] = self._values.js_apply(o.parent, stack);
|
157
|
+
m = values[i].size if (i==0)
|
158
|
+
stack.unshift(nil)
|
127
159
|
m.times {|j|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
y[_index[0]][j] = (h - o) / 2.0;
|
160
|
+
stack[0] = values[i][j]
|
161
|
+
o.index = j
|
162
|
+
x[j] = self._x.js_apply(o, stack) if i==0
|
163
|
+
dy[i][j] = self._y.js_apply(o, stack)
|
133
164
|
}
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
n.times {|i| o += dy[i][0] }
|
138
|
-
|
139
|
-
y[_index[0]][0] = o = (h - o) / 2.0
|
165
|
+
stack.shift()
|
166
|
+
}
|
167
|
+
stack.shift()
|
140
168
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
169
|
+
# order
|
170
|
+
_index=nil
|
171
|
+
case (s.order)
|
172
|
+
when "inside-out"
|
173
|
+
max = dy.map {|v| Rubyvis.max.index(v) }
|
174
|
+
map = pv.range(n).sort {|a,b| return max[a] - max[b]}
|
175
|
+
sums = dy.map {|v| Rubyvis.sum(v)}
|
176
|
+
top = 0
|
177
|
+
bottom = 0
|
178
|
+
tops = []
|
179
|
+
bottoms = []
|
146
180
|
n.times {|i|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
181
|
+
j = map[i]
|
182
|
+
if (top < bottom)
|
183
|
+
top += sums[j];
|
184
|
+
tops.push(j);
|
185
|
+
else
|
186
|
+
bottom += sums[j];
|
187
|
+
bottoms.push(j);
|
188
|
+
end
|
189
|
+
}
|
190
|
+
_index = bottoms.reverse+tops
|
191
|
+
|
192
|
+
when "reverse"
|
193
|
+
_index = Rubyvis.range(n - 1, -1, -1)
|
194
|
+
else
|
195
|
+
_index = Rubyvis.range(n)
|
196
|
+
end
|
197
|
+
|
198
|
+
#/* offset */
|
199
|
+
case (s.offset)
|
200
|
+
when "silohouette"
|
201
|
+
m.times {|j|
|
202
|
+
o = 0;
|
203
|
+
n.times {|i|
|
204
|
+
o += dy[i][j]
|
151
205
|
}
|
152
|
-
|
206
|
+
y[_index[0]][j] = (h - o) / 2.0;
|
153
207
|
}
|
154
|
-
|
155
|
-
|
208
|
+
|
209
|
+
when "wiggle"
|
210
|
+
o = 0;
|
211
|
+
n.times {|i| o += dy[i][0] }
|
156
212
|
|
157
|
-
|
158
|
-
|
213
|
+
y[_index[0]][0] = o = (h - o) / 2.0
|
214
|
+
|
215
|
+
(1...m).each {|j|
|
216
|
+
s1 = 0
|
217
|
+
s2 = 0
|
218
|
+
dx = x[j] - x[j - 1]
|
219
|
+
n.times {|i| s1 += dy[i][j]}
|
220
|
+
n.times {|i|
|
221
|
+
|
222
|
+
s3 = (dy[_index[i]][j] - dy[_index[i]][j - 1]) / (2.0 * dx)
|
223
|
+
i.times {|k|
|
224
|
+
s3 += (dy[_index[k]][j] - dy[_index[k]][j - 1]) / dx.to_f
|
225
|
+
}
|
226
|
+
s2 += s3 * dy[_index[i]][j]
|
227
|
+
}
|
228
|
+
o -= (s1!=0) ? s2 / s1.to_f * dx : 0
|
229
|
+
y[_index[0]][j] = o
|
230
|
+
|
231
|
+
}
|
232
|
+
when "expand"
|
233
|
+
m.times {|j|
|
234
|
+
y[_index[0]][j] = 0
|
235
|
+
|
236
|
+
k = 0
|
237
|
+
n.times {|i|k += dy[i][j]}
|
238
|
+
if (k!=0)
|
239
|
+
k = h / k.to_f
|
240
|
+
n.times {|i| dy[i][j] *= k}
|
241
|
+
else
|
242
|
+
k = h / n.to_f
|
243
|
+
n.times { dy[i][j] = k}
|
244
|
+
end
|
245
|
+
}
|
246
|
+
else
|
247
|
+
m.times {|j| y[_index[0]][j] = 0}
|
248
|
+
end
|
249
|
+
|
250
|
+
# Propagate the offset to the other series. */
|
159
251
|
m.times {|j|
|
160
|
-
|
252
|
+
o = y[_index[0]][j]
|
253
|
+
(1...n).each {|i|
|
161
254
|
|
162
|
-
|
163
|
-
|
164
|
-
if (k!=0)
|
165
|
-
k = h / k.to_f
|
166
|
-
n.times {|i| dy[i][j] *= k}
|
167
|
-
else
|
168
|
-
k = h / n.to_f
|
169
|
-
n.times { dy[i][j] = k}
|
170
|
-
end
|
255
|
+
o += dy[_index[i - 1]][j]
|
256
|
+
y[_index[i]][j] = o
|
171
257
|
}
|
172
|
-
|
173
|
-
|
258
|
+
}
|
259
|
+
|
260
|
+
# /* Find the property definitions for dynamic substitution. */
|
261
|
+
|
262
|
+
i = orient.index("-")
|
263
|
+
pdy = horizontal ? "h" : "w"
|
264
|
+
px = i < 0 ? (horizontal ? "l" : "b") : orient[i + 1,1]
|
265
|
+
py = orient[0,1]
|
266
|
+
|
267
|
+
@values=values
|
268
|
+
|
269
|
+
@prop.each {|k,v|
|
270
|
+
@prop[k]=@none
|
271
|
+
}
|
272
|
+
# puts "stack: x:#{px}, y:#{py}, dy:#{pdy}" if $DEBUG
|
273
|
+
@prop[px] =lambda {|i1,j| x[j]}
|
274
|
+
@prop[py] =lambda {|i1,j| y[i1][j]}
|
275
|
+
@prop[pdy]=lambda {|i1,j| dy[i1][j]}
|
174
276
|
end
|
175
277
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
278
|
+
def layer
|
279
|
+
that=self
|
280
|
+
value = Rubyvis::Mark.new().data(lambda { that.values[self.parent.index] }).top(proxy("t")).left(proxy("l")).right(proxy("r")).
|
281
|
+
bottom(proxy("b")).
|
282
|
+
width(proxy("w")).
|
283
|
+
height(proxy("h"))
|
180
284
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
pdy = horizontal ? "h" : "w"
|
190
|
-
px = i < 0 ? (horizontal ? "l" : "b") : orient[i + 1,1]
|
191
|
-
py = orient[0,1]
|
192
|
-
|
193
|
-
@values=values
|
194
|
-
|
195
|
-
@prop.each {|k,v|
|
196
|
-
@prop[k]=@none
|
197
|
-
}
|
198
|
-
# puts "stack: x:#{px}, y:#{py}, dy:#{pdy}" if $DEBUG
|
199
|
-
@prop[px] =lambda {|i1,j| x[j]}
|
200
|
-
@prop[py] =lambda {|i1,j| y[i1][j]}
|
201
|
-
@prop[pdy]=lambda {|i1,j| dy[i1][j]}
|
202
|
-
end
|
203
|
-
|
204
|
-
def layer
|
205
|
-
that=self
|
206
|
-
value = Rubyvis::Mark.new().data(lambda { that.values[self.parent.index] }).top(proxy("t")).left(proxy("l")).right(proxy("r")).
|
207
|
-
bottom(proxy("b")).
|
208
|
-
width(proxy("w")).
|
209
|
-
height(proxy("h"))
|
210
|
-
|
211
|
-
class << value
|
212
|
-
def that=(v)
|
213
|
-
@that = v
|
214
|
-
end
|
215
|
-
def add(type)
|
216
|
-
that = @that
|
217
|
-
that.add( Rubyvis.Panel ).data(lambda { that.layers() }).add(type).extend( self )
|
285
|
+
class << value # :nodoc:
|
286
|
+
def that=(v)
|
287
|
+
@that = v
|
288
|
+
end
|
289
|
+
def add(type)
|
290
|
+
that = @that
|
291
|
+
that.add( Rubyvis.Panel ).data(lambda { that.layers() }).add(type).extend( self )
|
292
|
+
end
|
218
293
|
end
|
294
|
+
|
295
|
+
value.that=self
|
296
|
+
return value
|
219
297
|
end
|
220
|
-
value.that=self
|
221
|
-
return value
|
222
298
|
end
|
223
299
|
end
|
224
|
-
end
|
225
300
|
end
|