opal-d3 0.0.20170205
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/Gemfile +3 -0
- data/README.md +7 -0
- data/Rakefile +31 -0
- data/d3.js +16393 -0
- data/demo/Gemfile +4 -0
- data/demo/README.md +7 -0
- data/demo/app/data/elections_2016.rb +10 -0
- data/demo/app/data/harry_potter.rb +19 -0
- data/demo/app/data/iphones.rb +29 -0
- data/demo/app/data/london_population.rb +26 -0
- data/demo/app/data/man_vs_horse.rb +55 -0
- data/demo/app/data/mtg_modern_colors.rb +96 -0
- data/demo/app/data/mtg_modern_creatures.rb +116 -0
- data/demo/app/data/olympics_2016_medals.rb +100 -0
- data/demo/app/data/paradox.rb +60 -0
- data/demo/app/data/polish_pms.rb +28 -0
- data/demo/app/data/star_trek_voyager.rb +183 -0
- data/demo/app/data/weather_in_london.rb +381 -0
- data/demo/app/elections_2016.rb +19 -0
- data/demo/app/harry_potter.rb +35 -0
- data/demo/app/iphones.rb +47 -0
- data/demo/app/london_population.rb +46 -0
- data/demo/app/london_population_area.rb +42 -0
- data/demo/app/man_vs_horse.rb +53 -0
- data/demo/app/mtg_modern_colors.rb +49 -0
- data/demo/app/mtg_modern_creatures.rb +63 -0
- data/demo/app/olympics_2016_medals.rb +54 -0
- data/demo/app/paradox.rb +57 -0
- data/demo/app/polish_pms.rb +53 -0
- data/demo/app/star_trek_voyager.rb +39 -0
- data/demo/app/weather_in_london.rb +62 -0
- data/demo/assets/d3.js +16393 -0
- data/demo/assets/style.css +0 -0
- data/demo/config.ru +39 -0
- data/demo/views/index.erb +21 -0
- data/demo/views/visualization.erb +29 -0
- data/lib/opal/d3/arc.rb +21 -0
- data/lib/opal/d3/area.rb +49 -0
- data/lib/opal/d3/axis.rb +77 -0
- data/lib/opal/d3/band_scale.rb +29 -0
- data/lib/opal/d3/collections.rb +10 -0
- data/lib/opal/d3/color.rb +78 -0
- data/lib/opal/d3/continuous_scale.rb +64 -0
- data/lib/opal/d3/creator.rb +11 -0
- data/lib/opal/d3/curve.rb +74 -0
- data/lib/opal/d3/dsv.rb +103 -0
- data/lib/opal/d3/ease.rb +319 -0
- data/lib/opal/d3/format.rb +97 -0
- data/lib/opal/d3/histograms.rb +44 -0
- data/lib/opal/d3/interpolate.rb +125 -0
- data/lib/opal/d3/line.rb +29 -0
- data/lib/opal/d3/map.rb +52 -0
- data/lib/opal/d3/misc.rb +15 -0
- data/lib/opal/d3/native.rb +84 -0
- data/lib/opal/d3/nest.rb +100 -0
- data/lib/opal/d3/ordinal_scale.rb +56 -0
- data/lib/opal/d3/path.rb +22 -0
- data/lib/opal/d3/pie.rb +23 -0
- data/lib/opal/d3/point_scale.rb +26 -0
- data/lib/opal/d3/polygon.rb +16 -0
- data/lib/opal/d3/quadtree.rb +95 -0
- data/lib/opal/d3/quantile_scale.rb +21 -0
- data/lib/opal/d3/quantize_scale.rb +23 -0
- data/lib/opal/d3/radial_area.rb +49 -0
- data/lib/opal/d3/radial_line.rb +29 -0
- data/lib/opal/d3/random.rb +12 -0
- data/lib/opal/d3/search.rb +28 -0
- data/lib/opal/d3/selection.rb +149 -0
- data/lib/opal/d3/sequential_scale.rb +96 -0
- data/lib/opal/d3/set.rb +33 -0
- data/lib/opal/d3/stack.rb +11 -0
- data/lib/opal/d3/statistics.rb +81 -0
- data/lib/opal/d3/symbol.rb +70 -0
- data/lib/opal/d3/threshold_scale.rb +23 -0
- data/lib/opal/d3/time_format.rb +48 -0
- data/lib/opal/d3/time_interval.rb +81 -0
- data/lib/opal/d3/transformations.rb +13 -0
- data/lib/opal/d3/version.rb +5 -0
- data/lib/opal/d3.rb +62 -0
- data/lib/opal-d3.rb +9 -0
- data/opal-d3.gemspec +20 -0
- data/spec/arc_spec.rb +86 -0
- data/spec/area_spec.rb +102 -0
- data/spec/axis_spec.rb +174 -0
- data/spec/band_scale_spec.rb +73 -0
- data/spec/color_spec.rb +74 -0
- data/spec/continuous_scale_spec.rb +217 -0
- data/spec/coverage_spec.rb +23 -0
- data/spec/creator_spec.rb +15 -0
- data/spec/curve_spec.rb +214 -0
- data/spec/dsv_spec.rb +194 -0
- data/spec/ease_spec.rb +370 -0
- data/spec/format_spec.rb +87 -0
- data/spec/histograms_spec.rb +61 -0
- data/spec/html/d3.js +16393 -0
- data/spec/html/index.html.erb +12 -0
- data/spec/interpolate_spec.rb +152 -0
- data/spec/line_spec.rb +58 -0
- data/spec/map_spec.rb +80 -0
- data/spec/misc_spec.rb +19 -0
- data/spec/nest_spec.rb +89 -0
- data/spec/objects_spec.rb +22 -0
- data/spec/ordinal_scale_spec.rb +59 -0
- data/spec/path_spec.rb +65 -0
- data/spec/pie_spec.rb +114 -0
- data/spec/point_scale_spec.rb +58 -0
- data/spec/polygon_spec.rb +51 -0
- data/spec/quadtree_spec.rb +128 -0
- data/spec/quantile_scale_spec.rb +24 -0
- data/spec/quantize_scale_spec.rb +40 -0
- data/spec/radial_area_spec.rb +127 -0
- data/spec/radial_line_spec.rb +54 -0
- data/spec/random_spec.rb +34 -0
- data/spec/search_spec.rb +69 -0
- data/spec/selection_data_spec.rb +71 -0
- data/spec/selection_manipulation_spec.rb +179 -0
- data/spec/selection_spec.rb +214 -0
- data/spec/sequential_scale_spec.rb +90 -0
- data/spec/set_spec.rb +57 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/stack_spec.rb +23 -0
- data/spec/statistics_spec.rb +65 -0
- data/spec/symbol_spec.rb +121 -0
- data/spec/threshold_scale_spec.rb +28 -0
- data/spec/time_format_spec.rb +99 -0
- data/spec/time_interval_spec.rb +304 -0
- data/spec/transformations_spec.rb +51 -0
- metadata +258 -0
@@ -0,0 +1,58 @@
|
|
1
|
+
describe "d3 - point scale" do
|
2
|
+
it "d3.scale_point" do
|
3
|
+
expect(D3.scale_point).to be_instance_of(D3::PointScale)
|
4
|
+
end
|
5
|
+
|
6
|
+
let(:d) { ("a".."f").to_a }
|
7
|
+
it "basics" do
|
8
|
+
scale = D3.scale_point.domain(d)
|
9
|
+
expect(d.map{|v| scale.(v).round(2)}).to eq([0, 0.2, 0.4, 0.6, 0.8, 1])
|
10
|
+
expect(scale.bandwidth).to eq(0)
|
11
|
+
expect(scale.step).to eq(0.2)
|
12
|
+
expect(scale.("z")).to eq(nil)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "copy" do
|
16
|
+
scale = D3.scale_point.domain(d)
|
17
|
+
sc = scale.copy.range([10,20])
|
18
|
+
expect(scale.domain).to eq(d)
|
19
|
+
expect(sc.domain).to eq(d)
|
20
|
+
expect(scale.range).to eq([0,1])
|
21
|
+
expect(sc.range).to eq([10,20])
|
22
|
+
end
|
23
|
+
|
24
|
+
it "padding" do
|
25
|
+
scale = D3.scale_point.domain(d).range([0,100])
|
26
|
+
expect(scale.padding).to eq(0)
|
27
|
+
|
28
|
+
scale.padding(0.5)
|
29
|
+
expect(scale.padding).to eq(0.5)
|
30
|
+
expect(d.map{|v| scale.(v).round(2)}).to eq([8.33, 25, 41.67, 58.33, 75, 91.67])
|
31
|
+
end
|
32
|
+
|
33
|
+
it "align" do
|
34
|
+
scale = D3.scale_point.domain(d).range([0,100])
|
35
|
+
scale.padding(0.5)
|
36
|
+
|
37
|
+
expect(scale.align).to eq(0.5)
|
38
|
+
expect(d.map{|v| scale.(v).round(2)}).to eq([8.33, 25, 41.67, 58.33, 75, 91.67])
|
39
|
+
|
40
|
+
scale.align(0)
|
41
|
+
expect(scale.align).to eq(0)
|
42
|
+
expect(d.map{|v| scale.(v).round(2)}).to eq([0, 16.67, 33.33, 50, 66.67, 83.33])
|
43
|
+
|
44
|
+
scale.align(1)
|
45
|
+
expect(scale.align).to eq(1)
|
46
|
+
expect(d.map{|v| scale.(v).round(2)}).to eq([16.67, 33.33, 50, 66.67, 83.33, 100])
|
47
|
+
end
|
48
|
+
|
49
|
+
it "round" do
|
50
|
+
scale = D3.scale_point.domain(d).range([0,100])
|
51
|
+
expect(scale.round).to eq(false)
|
52
|
+
scale.range_round([0,1000]).padding(1)
|
53
|
+
expect(scale.range).to eq([0,1000])
|
54
|
+
expect(scale.round).to eq(true)
|
55
|
+
# This rounding is somewhat weird
|
56
|
+
expect(d.map{|v| scale.(v)}).to eq([145, 287, 429, 571, 713, 855])
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
describe "d3 - polygon" do
|
2
|
+
let(:square) {
|
3
|
+
[[10,10], [40,10], [40,40], [10,40]]
|
4
|
+
}
|
5
|
+
let(:triangle) {
|
6
|
+
[[100,0], [160,0], [130, 40]]
|
7
|
+
}
|
8
|
+
let(:random_points) {[
|
9
|
+
[6, 39], [59, 86], [96, 20], [56, 5], [96, 98],
|
10
|
+
[70, 4], [47, 48], [77, 15], [2, 60], [41, 28],
|
11
|
+
[56, 59], [10, 15], [79, 12], [82, 97], [71, 14],
|
12
|
+
[18, 30], [64, 86], [35, 83], [49, 73], [78, 12],
|
13
|
+
]}
|
14
|
+
|
15
|
+
# signed area
|
16
|
+
it "d3.polygon_area" do
|
17
|
+
expect(D3.polygon_area(square)).to eq(-900)
|
18
|
+
expect(D3.polygon_area(triangle)).to eq(-1200)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "d3.polygon_centroid" do
|
22
|
+
expect(D3.polygon_centroid(square)).to eq([25, 25])
|
23
|
+
expect(D3.polygon_centroid(triangle)).to eq([130, 13.333333333333334])
|
24
|
+
end
|
25
|
+
|
26
|
+
it "d3.polygon_length" do
|
27
|
+
expect(D3.polygon_length(square)).to eq(120)
|
28
|
+
expect(D3.polygon_length(triangle)).to eq(160)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "d3.polygon_contains?" do
|
32
|
+
expect(D3.polygon_contains?(square, [20, 20])).to eq(true)
|
33
|
+
expect(D3.polygon_contains?(square, [50, 20])).to eq(false)
|
34
|
+
# Sometimes corners considered "inside"
|
35
|
+
expect(D3.polygon_contains?(square, [10, 10])).to eq(true)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "d3.polygon_hull" do
|
39
|
+
hull = D3.polygon_hull(random_points)
|
40
|
+
hull.each do |pt|
|
41
|
+
expect(random_points).to include(pt)
|
42
|
+
end
|
43
|
+
|
44
|
+
random_points.each do |pt|
|
45
|
+
# Sometimes corners not considered "inside"
|
46
|
+
expect(D3.polygon_contains?(hull, pt) || hull.include?(pt)).to eq(true)
|
47
|
+
end
|
48
|
+
|
49
|
+
expect(D3.polygon_hull([[10,10], [20,20]])).to eq(nil)
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
describe "d3 - quadtree" do
|
2
|
+
let(:a) { [1,2,"a"] }
|
3
|
+
let(:a2) { [1,2,"a"] }
|
4
|
+
let(:b) { [3,4,"b"] }
|
5
|
+
let(:c) { [5,6,"c"] }
|
6
|
+
let(:d) { [7,8,"c"] }
|
7
|
+
let(:e) { [3,4,"e"] }
|
8
|
+
|
9
|
+
it "d3.quadtree" do
|
10
|
+
expect(D3.quadtree).to be_instance_of(D3::QuadTree)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "quadtree.size" do
|
14
|
+
q = D3.quadtree
|
15
|
+
expect(q.size).to eq(0)
|
16
|
+
expect(q.add(a).size).to eq(1)
|
17
|
+
expect(q.add(b).size).to eq(2)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "quadtree.remove" do
|
21
|
+
q = D3.quadtree
|
22
|
+
expect(q.size).to eq(0)
|
23
|
+
expect(q.add(a).add(b).size).to eq(2)
|
24
|
+
expect(q.remove(a2).size).to eq(2)
|
25
|
+
expect(q.remove(a).size).to eq(1)
|
26
|
+
expect(q.remove(c).size).to eq(1)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "quadtree.remove_all" do
|
30
|
+
q = D3.quadtree([a,b,c])
|
31
|
+
expect(q.remove_all([b,d]).data).to eq([a,c])
|
32
|
+
end
|
33
|
+
|
34
|
+
it "quadtree.data" do
|
35
|
+
q = D3.quadtree
|
36
|
+
expect(q.data).to eq([])
|
37
|
+
expect(q.add(a).data).to eq([a])
|
38
|
+
expect(q.add_all([b,c]).data).to eq([a,b,c])
|
39
|
+
end
|
40
|
+
|
41
|
+
it "quadtree.find" do
|
42
|
+
q = D3.quadtree
|
43
|
+
expect(q.find(1,1)).to eq(nil)
|
44
|
+
q.add([1,2,"foo"])
|
45
|
+
expect(q.find(3,3)).to eq([1,2,"foo"])
|
46
|
+
expect(q.find(3,3,1)).to eq(nil)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "quadtree.copy" do
|
50
|
+
q1 = D3.quadtree.add(a)
|
51
|
+
q2 = q1.copy.add(b)
|
52
|
+
q1.add(c)
|
53
|
+
expect(q1.data).to eq([a,c])
|
54
|
+
expect(q2.data).to eq([a,b])
|
55
|
+
end
|
56
|
+
|
57
|
+
it "quadtree.visit" do
|
58
|
+
q = D3.quadtree([a,b,c,e])
|
59
|
+
called = []
|
60
|
+
q.visit do |node, x0, y0, x1, y1|
|
61
|
+
called << [x0, y0, x1, y1, node.internal?, node.leaf?, node.data, !!node.next, node.children && node.children.map{|x| !!x}]
|
62
|
+
false
|
63
|
+
end
|
64
|
+
expect(called).to eq([
|
65
|
+
[1, 2, 5, 6, true, false, nil, false, [true, false, false, true]],
|
66
|
+
[1, 2, 3, 4, false, true, [1, 2, "a"], false, nil],
|
67
|
+
[3, 4, 5, 6, true, false, nil, false, [true, false, false, true]],
|
68
|
+
[3, 4, 4, 5, false, true, [3, 4, "e"], true, nil],
|
69
|
+
[4, 5, 5, 6, false, true, [5, 6, "c"], false, nil],
|
70
|
+
])
|
71
|
+
end
|
72
|
+
|
73
|
+
it "quadtree.visit_after" do
|
74
|
+
q = D3.quadtree([a,b,c,e])
|
75
|
+
called = []
|
76
|
+
q.visit_after do |node, x0, y0, x1, y1|
|
77
|
+
called << [x0, y0, x1, y1, node.internal?, node.leaf?, node.data, !!node.next, node.children && node.children.map{|x| !!x}]
|
78
|
+
false
|
79
|
+
end
|
80
|
+
expect(called).to eq([
|
81
|
+
[1, 2, 3, 4, false, true, [1, 2, "a"], false, nil],
|
82
|
+
[3, 4, 4, 5, false, true, [3, 4, "e"], true, nil],
|
83
|
+
[4, 5, 5, 6, false, true, [5, 6, "c"], false, nil],
|
84
|
+
[3, 4, 5, 6, true, false, nil, false, [true, false, false, true]],
|
85
|
+
[1, 2, 5, 6, true, false, nil, false, [true, false, false, true]],
|
86
|
+
])
|
87
|
+
end
|
88
|
+
|
89
|
+
it "quadtree.root" do
|
90
|
+
q = D3.quadtree([a,b,c])
|
91
|
+
root = q.root
|
92
|
+
expect(root).to be_instance_of(D3::Quad)
|
93
|
+
expect(root).to be_internal
|
94
|
+
end
|
95
|
+
|
96
|
+
it "quadtree.extent" do
|
97
|
+
q = D3.quadtree([a,b,c])
|
98
|
+
expect(q.extent).to eq([[1, 2], [5, 6]])
|
99
|
+
expect(q.extent([[0,0],[10,1]]).extent([[-1,-1],[1,1]]).extent).to eq([[-3, -10], [13, 6]])
|
100
|
+
end
|
101
|
+
|
102
|
+
it "quadtree.cover" do
|
103
|
+
q = D3.quadtree([a,b,c])
|
104
|
+
expect(q.extent).to eq([[1, 2], [5, 6]])
|
105
|
+
expect(q.cover(0,0).cover(-2,10).extent).to eq([[-11, -2], [5, 14]])
|
106
|
+
end
|
107
|
+
|
108
|
+
it "quadtree.x/y defaults" do
|
109
|
+
q = D3.quadtree([a,b,c])
|
110
|
+
expect(q.x.(c)).to eq(5)
|
111
|
+
expect(q.y.(c)).to eq(6)
|
112
|
+
end
|
113
|
+
|
114
|
+
it "quadtree.x/y constructor" do
|
115
|
+
q = D3.quadtree([a,b,c], proc{|(x,y,n)| x*10}, proc{|(x,y,n)| y*10})
|
116
|
+
expect(q.x.(c)).to eq(50)
|
117
|
+
expect(q.y.(c)).to eq(60)
|
118
|
+
expect(q.extent).to eq([[10, 20], [74, 84]])
|
119
|
+
end
|
120
|
+
|
121
|
+
it "quadtree.x/y" do
|
122
|
+
q = D3.quadtree
|
123
|
+
q.x{|(x,y,n)| y*100}.y{|(x,y,n)| x*100}.add_all([a,b,c])
|
124
|
+
expect(q.x.(c)).to eq(600)
|
125
|
+
expect(q.y.(c)).to eq(500)
|
126
|
+
expect(q.extent).to eq([[200, 100], [712, 612]])
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
describe "d3 - quantile scale" do
|
2
|
+
it "d3.scale_quantile" do
|
3
|
+
expect(D3.scale_quantile).to be_instance_of(D3::QuantileScale)
|
4
|
+
end
|
5
|
+
|
6
|
+
it "basics" do
|
7
|
+
q = D3.scale_quantile.domain([0,10]).range(("a".."f").to_a)
|
8
|
+
expect(q.(4)).to eq("c")
|
9
|
+
|
10
|
+
expect(q.domain).to eq([0,10])
|
11
|
+
expect(q.range).to eq(("a".."f").to_a)
|
12
|
+
expect(q.quantiles).to eq([1.6666666666666665, 3.333333333333333, 5, 6.666666666666666, 8.333333333333334])
|
13
|
+
expect(q.invert_extent("e")).to eq([6.666666666666666, 8.333333333333334])
|
14
|
+
end
|
15
|
+
|
16
|
+
it "copy" do
|
17
|
+
q = D3.scale_quantile.domain([1,5]).range(["x", "y"])
|
18
|
+
qc = q.copy.domain([0,20])
|
19
|
+
expect(qc.domain).to eq([0,20])
|
20
|
+
expect(qc.range).to eq(["x", "y"])
|
21
|
+
expect(q.domain).to eq([1,5])
|
22
|
+
expect(q.range).to eq(["x", "y"])
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
describe "d3 - quantize scale" do
|
2
|
+
let(:color) { D3.scale_quantize.domain([0, 1]).range(["brown", "steelblue"]) }
|
3
|
+
let(:width) { D3.scale_quantize.domain([10, 100]).range([1, 2, 4]) }
|
4
|
+
|
5
|
+
it "d3.quantize_scale" do
|
6
|
+
expect(D3.scale_quantize).to be_instance_of(D3::QuantizeScale)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "basics - color" do
|
10
|
+
expect(color.(0.49)).to eq("brown")
|
11
|
+
expect(color.(0.51)).to eq("steelblue")
|
12
|
+
expect(color.domain).to eq([0,1])
|
13
|
+
expect(color.range).to eq(["brown", "steelblue"])
|
14
|
+
end
|
15
|
+
|
16
|
+
it "basics - width" do
|
17
|
+
expect(width.(20)).to eq(1)
|
18
|
+
expect(width.(50)).to eq(2)
|
19
|
+
expect(width.(80)).to eq(4)
|
20
|
+
expect(width.invert_extent(2)).to eq([40, 70])
|
21
|
+
end
|
22
|
+
|
23
|
+
it ".nice / .copy" do
|
24
|
+
s = D3.scale_quantize.domain([7, 109]).range([1, 2, 4])
|
25
|
+
sc = s.copy
|
26
|
+
expect(s.nice().domain).to eq([0, 110])
|
27
|
+
expect(sc.domain).to eq([7, 109])
|
28
|
+
end
|
29
|
+
|
30
|
+
it ".ticks" do
|
31
|
+
expect(width.ticks).to eq([10, 20, 30, 40, 50, 60, 70, 80, 90, 100])
|
32
|
+
expect(width.ticks(5)).to eq([20, 40, 60, 80, 100])
|
33
|
+
end
|
34
|
+
|
35
|
+
it ".tick_format" do
|
36
|
+
expect(width.tick_format.(30)).to eq("30")
|
37
|
+
expect(width.tick_format(5).(30)).to eq("30")
|
38
|
+
expect(width.tick_format(5, "+%").(30)).to eq("+3000%")
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
describe "d3 - radial area" do
|
2
|
+
it "d3.radial_area" do
|
3
|
+
expect(D3.radial_area).to be_instance_of(D3::RadialAreaGenerator)
|
4
|
+
end
|
5
|
+
|
6
|
+
let(:simple_data) {[
|
7
|
+
{year: 2007, value: 93.24},
|
8
|
+
{year: 2008, value: 95.35},
|
9
|
+
{year: 2009, value: 98.84},
|
10
|
+
{year: 2010, value: 99.92},
|
11
|
+
{year: 2011, value: 99.80},
|
12
|
+
{year: 2014, value: 99.47},
|
13
|
+
]}
|
14
|
+
|
15
|
+
describe "basics" do
|
16
|
+
let(:radial_area) {
|
17
|
+
D3.radial_area
|
18
|
+
.angle{|d| (d[:year]-2000)/10 }
|
19
|
+
.outer_radius{|d| d[:value] }
|
20
|
+
.inner_radius(50)
|
21
|
+
}
|
22
|
+
it "basics" do
|
23
|
+
expect(radial_area.(simple_data).gsub(/\d+\.\d+/){$&.to_f.round(2)}).to eq(%W[
|
24
|
+
M60.07,-71.31
|
25
|
+
L68.4,-66.43
|
26
|
+
L77.42,-61.44
|
27
|
+
L84.08,-53.99
|
28
|
+
L88.94,-45.27
|
29
|
+
L98.02,-16.91
|
30
|
+
L49.27,-8.5
|
31
|
+
L44.56,-22.68
|
32
|
+
L42.07,-27.02
|
33
|
+
L39.17,-31.08
|
34
|
+
L35.87,-34.84
|
35
|
+
L32.21,-38.24
|
36
|
+
Z
|
37
|
+
].join)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "curve" do
|
41
|
+
expect(radial_area.curve).to be_instance_of(D3::Curve)
|
42
|
+
expect(radial_area.curve(D3.curve_natural).(simple_data).gsub(/\d+\.\d+/){$&.to_f.round(2)}).to eq(%W[
|
43
|
+
M60.07,-71.31C62.74,-69.61,65.42,-67.91,68.4,-66.43
|
44
|
+
C71.38,-64.95,74.66,-63.68,77.42,-61.44
|
45
|
+
C80.19,-59.2,82.45,-55.98,84.08,-53.99
|
46
|
+
C85.71,-52,86.72,-51.24,88.94,-45.27
|
47
|
+
C91.16,-39.29,94.59,-28.1,98.02,-16.91
|
48
|
+
L49.27,-8.5
|
49
|
+
C47.49,-14.1,45.72,-19.7,44.56,-22.68
|
50
|
+
C43.4,-25.66,42.87,-26.01,42.07,-27.02
|
51
|
+
C41.28,-28.02,40.23,-29.66,39.17,-31.08
|
52
|
+
C38.1,-32.5,37.03,-33.68,35.87,-34.84
|
53
|
+
C34.71,-35.99,33.46,-37.12,32.21,-38.24
|
54
|
+
Z
|
55
|
+
].join)
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
it ".defined" do
|
60
|
+
expect(radial_area.defined{|d| d[:year] != 2010}.(simple_data).gsub(/\d+\.\d+/){$&.to_f.round(2)}).to eq(%W[
|
61
|
+
M60.07,-71.31
|
62
|
+
L68.4,-66.43
|
63
|
+
L77.42,-61.44
|
64
|
+
L39.17,-31.08
|
65
|
+
L35.87,-34.84
|
66
|
+
L32.21,-38.24
|
67
|
+
Z
|
68
|
+
M88.94,-45.27
|
69
|
+
L98.02,-16.91
|
70
|
+
L49.27,-8.5
|
71
|
+
L44.56,-22.68
|
72
|
+
Z
|
73
|
+
].join)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "line generators" do
|
78
|
+
let(:radial_area) {
|
79
|
+
D3.radial_area
|
80
|
+
.start_angle{|d| (d[:year]-2000)/20 }
|
81
|
+
.end_angle{|d| (d[:year]-2000)/10 }
|
82
|
+
.outer_radius{|d| d[:value] }
|
83
|
+
.inner_radius(50)
|
84
|
+
}
|
85
|
+
let(:point) { {year: 2042, value: 117 } }
|
86
|
+
|
87
|
+
it ".angle/.start_angle/.end_angle" do
|
88
|
+
expect(radial_area.start_angle.(point)).to eq(2.1)
|
89
|
+
expect(radial_area.end_angle.(point)).to eq(4.2)
|
90
|
+
expect(radial_area.angle.(point)).to eq(2.1)
|
91
|
+
end
|
92
|
+
|
93
|
+
it ".radius/.inner_radius/.outer_radius" do
|
94
|
+
expect(radial_area.inner_radius.(point)).to eq(50)
|
95
|
+
expect(radial_area.outer_radius.(point)).to eq(117)
|
96
|
+
expect(radial_area.radius.(point)).to eq(50)
|
97
|
+
end
|
98
|
+
|
99
|
+
it ".line_start_angle" do # start_angle inner_radius
|
100
|
+
expect(radial_area.line_start_angle).to be_instance_of(D3::RadialLineGenerator)
|
101
|
+
expect(radial_area.line_start_angle.angle.(point)).to eq(2.1)
|
102
|
+
expect(radial_area.line_start_angle.radius.(point)).to eq(50)
|
103
|
+
end
|
104
|
+
|
105
|
+
it ".line_end_angle" do # end_angle inner_radius
|
106
|
+
expect(radial_area.line_end_angle).to be_instance_of(D3::RadialLineGenerator)
|
107
|
+
expect(radial_area.line_end_angle.angle.(point)).to eq(4.2)
|
108
|
+
expect(radial_area.line_end_angle.radius.(point)).to eq(50)
|
109
|
+
end
|
110
|
+
|
111
|
+
it ".line_inner_radius" do # start_angle inner_radius
|
112
|
+
expect(radial_area.line_inner_radius).to be_instance_of(D3::RadialLineGenerator)
|
113
|
+
expect(radial_area.line_inner_radius.angle.(point)).to eq(2.1)
|
114
|
+
expect(radial_area.line_inner_radius.radius.(point)).to eq(50)
|
115
|
+
end
|
116
|
+
|
117
|
+
it ".line_outer_radius" do # start_angle outer_radius
|
118
|
+
expect(radial_area.line_outer_radius).to be_instance_of(D3::RadialLineGenerator)
|
119
|
+
expect(radial_area.line_outer_radius.angle.(point)).to eq(2.1)
|
120
|
+
expect(radial_area.line_outer_radius.radius.(point)).to eq(117)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
__END__
|
126
|
+
|
127
|
+
radialArea.context - set the rendering context.
|
@@ -0,0 +1,54 @@
|
|
1
|
+
describe "d3 - radial line" do
|
2
|
+
it "d3.radial_line" do
|
3
|
+
expect(D3.radial_line).to be_instance_of(D3::RadialLineGenerator)
|
4
|
+
end
|
5
|
+
|
6
|
+
let(:simple_data) { [[0,2],[Math::PI*0.10,5],[Math::PI*0.20,3]] }
|
7
|
+
|
8
|
+
it "basics" do
|
9
|
+
expect(D3.radial_line.(simple_data)).to eq("M0,-2L1.545084971874737,-4.755282581475767L1.7633557568774194,-2.4270509831248424")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "curve" do
|
13
|
+
expect(D3.radial_line.curve).to be_instance_of(D3::Curve)
|
14
|
+
expect(D3.radial_line.curve(D3.curve_natural).(simple_data)).to eq(%W[
|
15
|
+
M0,-2
|
16
|
+
C0.6255961728642502,-3.3420537088108135,1.2511923457285004,-4.684107417621627,1.545084971874737,-4.755282581475767
|
17
|
+
C1.8389775980209737,-4.826457745329908,1.8011666774491966,-3.626754364227375,1.7633557568774194,-2.4270509831248424
|
18
|
+
].join)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "angle/radius accessors" do
|
22
|
+
radial_line = D3.radial_line
|
23
|
+
radial_line.angle{|(a,r)| a*2}.radius{|(a,r)| r*100}
|
24
|
+
expect(radial_line.angle.([2,42])).to eq(4)
|
25
|
+
expect(radial_line.radius.([2,42])).to eq(4200)
|
26
|
+
expect(radial_line.(simple_data)).to eq("M0,-200L293.8926261462366,-404.5084971874737L285.31695488854604,-92.70509831248424")
|
27
|
+
end
|
28
|
+
|
29
|
+
it ".angle constant" do
|
30
|
+
radial_line = D3.radial_line.angle(Math::PI)
|
31
|
+
expect(radial_line.(simple_data)).to eq("M2.4492935982947064e-16,2L6.123233995736766e-16,5L3.6739403974420594e-16,3")
|
32
|
+
expect(radial_line.angle.(42)).to eq(Math::PI)
|
33
|
+
radial_line.angle = 20
|
34
|
+
expect(radial_line.angle.(42)).to eq(20)
|
35
|
+
end
|
36
|
+
|
37
|
+
it ".radius constant" do
|
38
|
+
radial_line = D3.radial_line.radius(10)
|
39
|
+
expect(radial_line.(simple_data)).to eq("M0,-10L3.090169943749474,-9.510565162951535L5.877852522924732,-8.090169943749475")
|
40
|
+
expect(radial_line.radius.(42)).to eq(10)
|
41
|
+
radial_line.radius = 20
|
42
|
+
expect(radial_line.radius.(42)).to eq(20)
|
43
|
+
end
|
44
|
+
|
45
|
+
it ".defined" do
|
46
|
+
radial_line = D3.radial_line.defined{|(a,r)| r.even?}
|
47
|
+
data = [[0,6], [0,10], [0,11], [0,14], [0,16], [0,19]]
|
48
|
+
expect(radial_line.(data)).to eq("M0,-6L0,-10M0,-14L0,-16")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
__END__
|
53
|
+
|
54
|
+
radialLine.context - set the rendering context.
|
data/spec/random_spec.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
describe "d3-random" do
|
2
|
+
# Not really testing anything more meaningful,
|
3
|
+
# just that they return some numbers
|
4
|
+
# http://xkcd.com/221/
|
5
|
+
it "d3.random_uniform" do
|
6
|
+
expect(D3.random_uniform.call).to be_a(Numeric)
|
7
|
+
expect(D3.random_uniform(10).call).to be_a(Numeric)
|
8
|
+
expect(D3.random_uniform(10,20).call).to be_a(Numeric)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "d3.random_normal" do
|
12
|
+
expect(D3.random_normal.call).to be_a(Numeric)
|
13
|
+
expect(D3.random_normal(10).call).to be_a(Numeric)
|
14
|
+
expect(D3.random_normal(10, 2).call).to be_a(Numeric)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "d3.random_log_normal" do
|
18
|
+
expect(D3.random_log_normal.call).to be_a(Numeric)
|
19
|
+
expect(D3.random_log_normal(10).call).to be_a(Numeric)
|
20
|
+
expect(D3.random_log_normal(10, 2).call).to be_a(Numeric)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "d3.random_bates" do
|
24
|
+
expect(D3.random_bates(5).call).to be_a(Numeric)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "d3.random_irwin_hall" do
|
28
|
+
expect(D3.random_irwin_hall(5).call).to be_a(Numeric)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "d3.random_exponential" do
|
32
|
+
expect(D3.random_exponential(3).call).to be_a(Numeric)
|
33
|
+
end
|
34
|
+
end
|
data/spec/search_spec.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
describe "d3-array - search" do
|
2
|
+
it "d3.ascending" do
|
3
|
+
expect(D3.ascending(2,1)).to eq(1)
|
4
|
+
expect(D3.ascending(1,1)).to eq(0)
|
5
|
+
expect(D3.ascending(1,2)).to eq(-1)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "d3.descending" do
|
9
|
+
expect(D3.descending(2,1)).to eq(-1)
|
10
|
+
expect(D3.descending(1,1)).to eq(0)
|
11
|
+
expect(D3.descending(1,2)).to eq(1)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "d3.scan" do
|
15
|
+
array = [13,5,11,26,32]
|
16
|
+
expect(D3.scan(array)).to eq(1)
|
17
|
+
expect(D3.scan(array){|a,b| (a%10) - (b%10)}).to eq(2)
|
18
|
+
expect(D3.scan(array){|a,b| (b%10) - (a%10)}).to eq(3)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "d3.bisect_left" do
|
22
|
+
array = (100..200).to_a
|
23
|
+
expect(D3.bisect_left(array, 117)).to eq(17)
|
24
|
+
expect(D3.bisect_left(array, 130.5)).to eq(31)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "d3.bisect_right" do
|
28
|
+
array = (100..200).to_a
|
29
|
+
expect(D3.bisect_right(array, 117)).to eq(18)
|
30
|
+
expect(D3.bisect_right(array, 130.5)).to eq(31)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "d3.bisect" do
|
34
|
+
array = (100..200).to_a
|
35
|
+
expect(D3.bisect(array, 117)).to eq(18)
|
36
|
+
expect(D3.bisect(array, 130.5)).to eq(31)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "d3.bisector" do
|
40
|
+
expect(D3.bisector{|x| x.abs}).to be_instance_of(D3::Bisector)
|
41
|
+
expect(D3.bisector{|x,y| x.abs - y.abs}).to be_instance_of(D3::Bisector)
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "D3::Bisector" do
|
45
|
+
let(:array) { (100..200).map{|i| i * (-1)**i} }
|
46
|
+
let(:a) { D3.bisector{|x| x.abs} }
|
47
|
+
let(:c) { D3.bisector{|x,y| x.abs - y.abs} }
|
48
|
+
|
49
|
+
it "A.left" do
|
50
|
+
expect(a.left(array, 117)).to eq(17)
|
51
|
+
expect(a.left(array, 130.5)).to eq(31)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "C.left" do
|
55
|
+
expect(c.left(array, 117)).to eq(17)
|
56
|
+
expect(c.left(array, 130.5)).to eq(31)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "A.right" do
|
60
|
+
expect(a.right(array, 117)).to eq(18)
|
61
|
+
expect(a.right(array, 130.5)).to eq(31)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "C.right" do
|
65
|
+
expect(c.right(array, 117)).to eq(18)
|
66
|
+
expect(c.right(array, 130.5)).to eq(31)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
describe "d3 - selection - data" do
|
2
|
+
after(:each) do
|
3
|
+
D3.select("#test-area").html("")
|
4
|
+
end
|
5
|
+
let(:root) { D3.select("#test-area") }
|
6
|
+
let(:html) { root.html }
|
7
|
+
|
8
|
+
describe "list" do
|
9
|
+
let(:data) {[
|
10
|
+
{name: "A", value: 10},
|
11
|
+
{name: "B", value: 20},
|
12
|
+
{name: "C", value: 30},
|
13
|
+
]}
|
14
|
+
it "enter" do
|
15
|
+
root
|
16
|
+
.append("ul")
|
17
|
+
.select_all("li")
|
18
|
+
.data(data)
|
19
|
+
.enter
|
20
|
+
.append("li")
|
21
|
+
.html{|d| "<b>#{d[:name]}</b>"}
|
22
|
+
.style("font-size"){|d| "#{d[:value]}px"}
|
23
|
+
expect(html).to eq([
|
24
|
+
%Q[<ul>],
|
25
|
+
%Q[<li style="font-size: 10px;"><b>A</b></li>],
|
26
|
+
%Q[<li style="font-size: 20px;"><b>B</b></li>],
|
27
|
+
%Q[<li style="font-size: 30px;"><b>C</b></li>],
|
28
|
+
%Q[</ul>],
|
29
|
+
].join)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "matrix" do
|
34
|
+
let(:data) {
|
35
|
+
[
|
36
|
+
[11975, 5871, 8916, 2868],
|
37
|
+
[ 1951, 10048, 2060, 6171],
|
38
|
+
[ 8010, 16145, 8090, 8045],
|
39
|
+
[ 1013, 990, 940, 6907],
|
40
|
+
]
|
41
|
+
}
|
42
|
+
it do
|
43
|
+
tr = root
|
44
|
+
.append("table")
|
45
|
+
.select_all("tr")
|
46
|
+
.data(data)
|
47
|
+
.enter
|
48
|
+
.append("tr")
|
49
|
+
tr.select_all("td")
|
50
|
+
.data{|d| d}
|
51
|
+
.enter
|
52
|
+
.append("td")
|
53
|
+
.text{|d| d}
|
54
|
+
expect(html).to eq([
|
55
|
+
%Q[<table>],
|
56
|
+
%Q[<tr><td>11975</td><td>5871</td><td>8916</td><td>2868</td></tr>],
|
57
|
+
%Q[<tr><td>1951</td><td>10048</td><td>2060</td><td>6171</td></tr>],
|
58
|
+
%Q[<tr><td>8010</td><td>16145</td><td>8090</td><td>8045</td></tr>],
|
59
|
+
%Q[<tr><td>1013</td><td>990</td><td>940</td><td>6907</td></tr>],
|
60
|
+
%Q[</table>],
|
61
|
+
].join)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
__END__
|
67
|
+
|
68
|
+
.data key
|
69
|
+
|
70
|
+
selection.exit - get the exit selection (elements missing data).
|
71
|
+
selection.datum - get or set element data (without joining).
|