rubyvis 0.1.7 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig CHANGED
Binary file
data/History.txt CHANGED
@@ -1,3 +1,15 @@
1
+ === 0.2.0 / 2010-11-02
2
+
3
+ * IMPORTANT: Added 'ruby best practices' API. See README and examples/first_rbp_api.rb to learn how to use
4
+ * Added width and height explicitly on examples pages.
5
+ * Added examples for interpolation on lines and areas
6
+ * Fixed interpolate for lines and areas.
7
+ * New spec for Line and Area spec.
8
+ * Added spec for numeric tick_format
9
+ * Added documentation for Rubyvis::Colors, Rubyvis::Color and Rubyvis::Line
10
+ * Bug fix: interpolate "step-after", "step-before" and "basis" on Area marks doesn't work Spec for Area marks
11
+ * Changed API_VERSION for PROTOVIS_API_VERSION
12
+
1
13
  === 0.1.7 / 2010-10-31
2
14
 
3
15
  * Added image support
data/Manifest.txt CHANGED
@@ -5,6 +5,7 @@ Rakefile
5
5
  examples/antibiotics/antibiotics.rb
6
6
  examples/antibiotics/antibiotics_data.rb
7
7
  examples/area.rb
8
+ examples/area_interpolation.rb
8
9
  examples/bar_column_chart.rb
9
10
  examples/barley/barley.rb
10
11
  examples/barley/barley_data.rb
@@ -12,13 +13,15 @@ examples/crimea/crimea_data.rb
12
13
  examples/crimea/crimea_grouped_bar.rb
13
14
  examples/crimea/crimea_line.rb
14
15
  examples/dot.rb
15
- examples/first.rb
16
+ examples/first_protovis_api.rb
17
+ examples/first_rbp_api.rb
16
18
  examples/fixtures/tipsy.gif
17
19
  examples/grouped_charts.rb
18
20
  examples/image.rb
19
21
  examples/image.svg
20
22
  examples/line.rb
21
23
  examples/line_and_step.rb
24
+ examples/line_interpolation.rb
22
25
  examples/nested_grid.rb
23
26
  examples/pie_and_donut.rb
24
27
  examples/scatterplot.rb
@@ -28,7 +31,6 @@ examples/third.rb
28
31
  lib/rubyvis.rb
29
32
  lib/rubyvis/color/color.rb
30
33
  lib/rubyvis/color/colors.rb
31
- lib/rubyvis/color/ramp.rb
32
34
  lib/rubyvis/format.rb
33
35
  lib/rubyvis/format/date.rb
34
36
  lib/rubyvis/format/number.rb
@@ -46,6 +48,7 @@ lib/rubyvis/mark/label.rb
46
48
  lib/rubyvis/mark/line.rb
47
49
  lib/rubyvis/mark/panel.rb
48
50
  lib/rubyvis/mark/rule.rb
51
+ lib/rubyvis/mark/shorcut_methods.rb
49
52
  lib/rubyvis/mark/wedge.rb
50
53
  lib/rubyvis/nest.rb
51
54
  lib/rubyvis/property.rb
@@ -56,6 +59,7 @@ lib/rubyvis/scale/ordinal.rb
56
59
  lib/rubyvis/scale/quantitative.rb
57
60
  lib/rubyvis/scene/svg_area.rb
58
61
  lib/rubyvis/scene/svg_bar.rb
62
+ lib/rubyvis/scene/svg_curve.rb
59
63
  lib/rubyvis/scene/svg_dot.rb
60
64
  lib/rubyvis/scene/svg_image.rb
61
65
  lib/rubyvis/scene/svg_label.rb
@@ -67,13 +71,16 @@ lib/rubyvis/scene/svg_wedge.rb
67
71
  lib/rubyvis/sceneelement.rb
68
72
  lib/rubyvis/transform.rb
69
73
  spec/anchor_spec.rb
74
+ spec/area_spec.rb
70
75
  spec/bar_spec.rb
71
76
  spec/internal_spec.rb
72
77
  spec/javascript_behaviour_spec.rb
73
78
  spec/label_spec.rb
79
+ spec/line_spec.rb
74
80
  spec/mark_spec.rb
75
81
  spec/nest_spec.rb
76
82
  spec/panel_spec.rb
83
+ spec/ruby_api_spec.rb
77
84
  spec/scale_linear_datetime_spec.rb
78
85
  spec/scale_linear_spec.rb
79
86
  spec/scale_log_spec.rb
data/README.txt CHANGED
@@ -8,7 +8,7 @@ Ruby port of Protovis[http://vis.stanford.edu/protovis/], a great visualization
8
8
 
9
9
  == FEATURES/PROBLEMS:
10
10
 
11
- Implemented: All marks, except transient, image and transition.
11
+ Implemented: All marks, except transient and transitions.
12
12
 
13
13
  Basic protovis examples[http://vis.stanford.edu/protovis/ex/] works exactly like ruby ones with minor sintactic modifications:
14
14
  * Area Charts: Ok
@@ -28,10 +28,6 @@ Complex examples requires more works:
28
28
 
29
29
  I try to maintain, when posible, complete compatibility with Javascript API, including camel case naming of functions. Johnson [http://github.com/jbarnette/johnson] - the lovely Javascript wrapper inside Ruby embrace - is our friend to test implementation of basic object.
30
30
 
31
- Until version 0.1.0, lambdas should always should created explicitly for method you may be temted to call it with a block.
32
-
33
- On a second stage, traditional block calling could be using maintaining backwards compatibily with Javascript API. See TODO section for proposal of new API.
34
-
35
31
  User could use +pv+ freely, cause is defined as a global method which call Rubyvis.
36
32
 
37
33
  == CURRENT PROGRESS
@@ -69,70 +65,45 @@ User could use +pv+ freely, cause is defined as a global method which call Rubyv
69
65
 
70
66
  == SYNOPSIS:
71
67
 
68
+ The primary API, based on Gregory Brown's Ruby Best Practices, uses blocks and name of marks as methods
69
+
72
70
  require 'rubyvis'
73
71
 
74
- vis = Rubyvis::Panel.new.width(150).height(150);
75
- vis.add(pv.Bar).data([1, 1.2, 1.7, 1.5, 0.7, 0.3]).
76
- width(20).
77
- height(lambda {|d| d * 80}).
78
- bottom(0).
79
- left(lambda {self.index * 25});
72
+ vis = Rubyvis::Panel.new do
73
+ width 150
74
+ height 150
75
+ bar do
76
+ data [1, 1.2, 1.7, 1.5, 0.7, 0.3]
77
+ width 20
78
+ height {|d| d * 80}
79
+ bottom(0)
80
+ left {index * 25}
81
+ end
82
+ end
83
+
80
84
  vis.render
81
85
  puts vis.to_svg
82
-
83
- See examples directory for original protovis examples adaptations.
84
-
85
- == TODO
86
86
 
87
- Implement a ruby-like API, like ReportBuilder[http://ruby-statsample.rubyforge.org/reportbuilder/] or Prawn [http://prawn.majesticseacreature.com/docs/]
88
87
 
89
- The examples/area.rb script should like somethink like that
88
+ The library allows you to use chain methods API, like original protovis
90
89
 
91
90
  require 'rubyvis'
92
- vis = Rubyvis::Panel.new {
93
- width w
94
- height h
95
- bottom 20
96
- left 20
97
- right 10
98
- top 5
99
- # Y-axis
100
- rule {
101
- data y.ticks(5)
102
- bottom y
103
- stroke_style {|d| d!=0 ? "#eee" : "#000"}
104
- anchor("left") {
105
- label {
106
- text y.tick_format
107
- }
108
- }
109
- }
110
- # X-axis
111
- rule {
112
- data x.ticks
113
- visible {|d| d!=0}
114
- left x
115
- bottom -5
116
- height -5
117
- label(:anchor=>'bottom') { # shortcut to create a mark inside an anchor
118
- text x.tick_format
119
- }
120
- }
121
-
122
- # The area with top line.
123
- area {
124
- data(data)
125
- bottom 1
126
- left {|d| x.scale(d.x)}
127
- height {|d| y.scale(d.y)}
128
- fill_style "rgb(121,173,210)"
129
- line(:anchor=>"top") {
130
- line_width 3
131
- }
132
- }
133
- }
134
91
 
92
+ vis = Rubyvis::Panel.new.width(150).height(150);
93
+
94
+ vis.add(pv.Bar).
95
+ data([1, 1.2, 1.7, 1.5, 0.7, 0.3]).
96
+ width(20).
97
+ height(lambda {|d| d * 80}).
98
+ bottom(0).
99
+ left(lambda {self.index * 25});
100
+
101
+ vis.render
135
102
  puts vis.to_svg
103
+
104
+
105
+ See examples directory for original protovis examples adaptations and others graphics
106
+
136
107
 
137
108
 
138
109
  == REQUIREMENTS:
@@ -0,0 +1,56 @@
1
+ # = Area Interpolation
2
+ # This example show the 5 types of interpolation available for areas.
3
+ $:.unshift(File.dirname(__FILE__)+"/../lib")
4
+ require 'rubyvis'
5
+
6
+ data = pv.range(0, 10, 0.5).map {|x|
7
+ OpenStruct.new({:x=> x, :y=> Math.sin(x) + 2+rand()*0.3})
8
+ }
9
+
10
+ p_w=200
11
+ p_h=150
12
+ #p data
13
+ w = 20+p_w*2
14
+ h = 20+p_h*3
15
+
16
+ x = pv.Scale.linear(data, lambda {|d| d.x}).range(0, p_w-30)
17
+ y = pv.Scale.linear(data, lambda {|d| d.y}).range(0, p_h-20);
18
+ interpolations=["linear","step-before","step-after", "basis", "cardinal"]
19
+
20
+ vis = Rubyvis::Panel.new do |pan|
21
+ pan.width w
22
+ pan.height h
23
+ pan.bottom 20
24
+ pan.left 20
25
+ pan.right 10
26
+ pan.top 5
27
+
28
+ interpolations.each_with_index do |inter,i|
29
+ n=i%2
30
+ m=(i/2).floor
31
+ pan.panel do
32
+ left(n*(p_w+10))
33
+ top(m*(p_h+10))
34
+ width p_w
35
+ height p_h
36
+ label(:anchor=>'top') do
37
+ text(inter)
38
+ end
39
+ # uses 'a' as reference inside block
40
+ # to use data method with data variable
41
+ area do |a|
42
+ a.data data
43
+ a.left {|d| x.scale(d.x)}
44
+ a.height {|d| y.scale(d.y)}
45
+ a.bottom 1
46
+ a.interpolate inter
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+
53
+ vis.render();
54
+
55
+
56
+ puts vis.to_svg
@@ -1,5 +1,5 @@
1
1
  # = First example
2
- # This is the ruby version of "Getting Started" example of Protovis introduction.
2
+ # This is the protovis API version of "Getting Started" example of Protovis introduction.
3
3
  # On this example we show you how can you build a bar chart using panel and bar marks.
4
4
  # A mark represents a set of graphical elements that share data and visual encodings. Although marks are simple by themselves, you can combine them in interesting ways to make rich, interactive visualizations
5
5
  $:.unshift(File.dirname(__FILE__)+"/../lib")
@@ -0,0 +1,21 @@
1
+ # = First example
2
+ # This is the RBP API version of "Getting Started" example of Protovis introduction.
3
+ # On this example we show you how can you build a bar chart using panel and bar marks.
4
+ # A mark represents a set of graphical elements that share data and visual encodings. Although marks are simple by themselves, you can combine them in interesting ways to make rich, interactive visualizations
5
+ $:.unshift(File.dirname(__FILE__)+"/../lib")
6
+ require 'rubyvis'
7
+
8
+ vis = Rubyvis::Panel.new do
9
+ width 150
10
+ height 150
11
+ bar do
12
+ data [1, 1.2, 1.7, 1.5, 0.7, 0.3]
13
+ width 20
14
+ height {|d| d * 80}
15
+ bottom(0)
16
+ left {index * 25}
17
+ end
18
+ end
19
+
20
+ vis.render
21
+ puts vis.to_svg
data/examples/image.rb CHANGED
@@ -16,5 +16,4 @@ dot=vis.add(pv.Image)
16
16
  .url(img_url)
17
17
 
18
18
  vis.render()
19
- #puts vis.children_inspect
20
19
  puts vis.to_svg
data/examples/line.rb CHANGED
@@ -25,7 +25,6 @@ vis = pv.Panel.new()
25
25
  .right(10)
26
26
  .top(5)
27
27
 
28
- #/* The area with top line. */
29
28
  vis.add(pv.Line).
30
29
  data(data).
31
30
  line_width(5).
@@ -0,0 +1,55 @@
1
+ # = Line Interpolation
2
+ # This example show the 7 types of interpolation available for lines.
3
+ $:.unshift(File.dirname(__FILE__)+"/../lib")
4
+ require 'rubyvis'
5
+
6
+ data = pv.range(0, 10, 1).map {|x|
7
+ OpenStruct.new({:x=> x, :y=> Math.sin(x) + 2+rand()*0.2})
8
+ }
9
+
10
+ p_w=200
11
+ p_h=150
12
+ #p data
13
+ w = 20+p_w*2
14
+ h = 20+p_h*4
15
+
16
+ x = pv.Scale.linear(data, lambda {|d| d.x}).range(0, p_w-30)
17
+
18
+
19
+ y = pv.Scale.linear(data, lambda {|d| d.y}).range(0, p_h-20);
20
+
21
+ interpolations=["linear","step-before","step-after","polar","polar-reverse", "basis", "cardinal"]
22
+
23
+ #/* The root panel. */
24
+ vis = pv.Panel.new()
25
+ .width(w)
26
+ .height(h)
27
+ .bottom(20)
28
+ .left(20)
29
+ .right(10)
30
+ .top(5)
31
+
32
+ interpolations.each_with_index do |inter,i|
33
+ n=i%2
34
+ m=(i/2).floor
35
+ panel=vis.add(Rubyvis::Panel).
36
+ left(n*(p_w+10)).
37
+ top(m*(p_h+10)).
38
+ width(p_w).
39
+ height(p_h)
40
+ panel.anchor('top').add(Rubyvis::Label).text(inter)
41
+ panel.add(Rubyvis::Line).data(data).
42
+ line_width(2).
43
+ left(lambda {|d| x.scale(d.x)}).
44
+ bottom(lambda {|d| y.scale(d.y)}).
45
+ interpolate(inter)
46
+
47
+ end
48
+
49
+
50
+
51
+
52
+ vis.render();
53
+
54
+
55
+ puts vis.to_svg
data/lib/rubyvis.rb CHANGED
@@ -22,12 +22,13 @@ require 'rubyvis/scene/svg_scene'
22
22
  require 'rubyvis/transform'
23
23
 
24
24
 
25
+
25
26
  module Rubyvis
26
27
  @document=nil
27
28
  # Rubyvis version
28
- VERSION = '0.1.7'
29
+ VERSION = '0.2.0'
29
30
  # Protovis API on which current Rubyvis is based
30
- API_VERSION='3.3'
31
+ PROTOVIS_API_VERSION='3.3'
31
32
  # You actually can do it! http://snipplr.com/view/2137/uses-for-infinity-in-ruby/
32
33
  Infinity=1.0 / 0
33
34
  #
@@ -89,4 +90,3 @@ end
89
90
  def pv
90
91
  Rubyvis
91
92
  end
92
-
@@ -1,5 +1,29 @@
1
1
  module Rubyvis
2
-
2
+ # Returns the Rubyvis::Color for the specified color format string. Colors
3
+ # may have an associated opacity, or alpha channel.
4
+ # Color formats are specified by CSS Color Modular Level 3,
5
+ # using either in RGB or HSL color space. For example:<ul>
6
+ #
7
+ # <li>#f00 // #rgb
8
+ # <li>#ff0000 // #rrggbb
9
+ # <li>rgb(255, 0, 0)
10
+ # <li>rgb(100%, 0%, 0%)
11
+ # <li>hsl(0, 100%, 50%)
12
+ # <li>rgba(0, 0, 255, 0.5)
13
+ # <li>hsla(120, 100%, 50%, 1)
14
+ # </ul>
15
+ #
16
+ # The SVG 1.0 color keywords names are also supported, such as "aliceblue"
17
+ # and "yellowgreen". The "transparent" keyword is supported for fully-
18
+ # transparent black.
19
+ #
20
+ # <p>If the <tt>format</tt> argument is already an instance of <tt>Color</tt>,
21
+ # the argument is returned with no further processing.
22
+ #
23
+ # * see <a href="http://www.w3.org/TR/SVG/types.html#ColorKeywords">SVG color
24
+ # keywords</a>
25
+ # * see <a href="http://www.w3.org/TR/css3-color/">CSS3 color module</a>
26
+ #/
3
27
  def self.color(format)
4
28
  return format.rgb if format.respond_to? :rgb
5
29
  if (format =~/([a-z]+)\((.*)\)/)
@@ -51,22 +75,53 @@ module Rubyvis
51
75
  # Otherwise, pass-through unsupported colors. */
52
76
  return Rubyvis::Color.new(format, 1);
53
77
  end
54
-
78
+ # Constructs a new RGB color with the specified channel values.
55
79
  def self.rgb(r,g,b,a=1)
56
80
  Rubyvis::Color::Rgb.new(r,g,b,a)
57
81
  end
58
-
82
+ def self.hsl(h,s,l,a=1)
83
+ Rubyvis::Color::Hsl.new(h,s,l,a)
84
+ end
85
+ # Represents an abstract (possibly translucent) color. The color is
86
+ # divided into two parts: the <tt>color</tt> attribute, an opaque color format
87
+ # string, and the <tt>opacity</tt> attribute, a float in [0, 1]. The color
88
+ # space is dependent on the implementing class; all colors support the
89
+ # Color.rgb() method to convert to RGB color space for interpolation.
59
90
  class Color
60
- attr_reader :color, :opacity
91
+ # An opaque color format string, such as "#f00".
92
+ attr_reader :color
93
+ # The opacity, a float in [0, 1].
94
+ attr_reader :opacity
95
+
96
+ # Constructs a color with the specified color format string and opacity. This
97
+ # constructor should not be invoked directly; use Rubyvis.color instead.
61
98
  def initialize(color,opacity)
62
99
  @color=color
63
100
  @opacity=opacity
64
101
  end
65
- def darker(*args)
66
- self.rgb.darker(*args)
102
+ # Returns a new color that is a brighter version of this color. The behavior of
103
+ # this method may vary slightly depending on the underlying color space.
104
+ # Although brighter and darker are inverse operations, the results of a series
105
+ # of invocations of these two methods might be inconsistent because of rounding
106
+ # errors.
107
+ # * @param [k] {number} an optional scale factor; defaults to 1.
108
+ def brighter(k)
109
+ self.rgb.lighter(k)
67
110
  end
68
-
69
- def self.names
111
+
112
+ # Returns a new color that is a brighter version of this color. The behavior of
113
+ # this method may vary slightly depending on the underlying color space.
114
+ # Although brighter and darker are inverse operations, the results of a series
115
+ # of invocations of these two methods might be inconsistent because of rounding
116
+ # errors.
117
+ #
118
+ # * @param [k] {number} an optional scale factor; defaults to 1.
119
+ def darker(k)
120
+ self.rgb.darker(k)
121
+ end
122
+
123
+ # Association between names and colors
124
+ def self.names # :nodoc:
70
125
  {
71
126
  :aliceblue=>"#f0f8ff",
72
127
  :antiquewhite=>"#faebd7",
@@ -220,10 +275,17 @@ module Rubyvis
220
275
  def self.transparent
221
276
  Rubyvis.rgb(0,0,0,0)
222
277
  end
223
-
224
-
278
+ # Represents a color in RGB space.
225
279
  class Rgb < Color
226
- attr_reader :r, :b, :g, :a
280
+ # The red channel, an integer in [0, 255].
281
+ attr_reader :r
282
+ # The blue channel, an integer in [0, 255].
283
+ attr_reader :b
284
+ # The green channel, an integer in [0, 255].
285
+ attr_reader :g
286
+ # The alpha channel, a float in [0, 1].
287
+ attr_reader :a
288
+ # Constructs a new RGB color with the specified channel values.
227
289
  def initialize(r,g,b,a)
228
290
  @r=r
229
291
  @b=b
@@ -239,34 +301,129 @@ module Rubyvis
239
301
  def ==(v)
240
302
  self.class==v.class and @r==v.r and @b==v.b and @g=v.g and @a=v.a
241
303
  end
304
+
305
+ # Constructs a new RGB color with the same green, blue and alpha channels
306
+ # as this color, with the specified red channel.
242
307
  def red(r1)
243
308
  Rubyvis.rgb(r1,g,b,a)
244
309
  end
310
+ # Constructs a new RGB color with the same red, blue and alpha channels
311
+ # as this color, with the specified green channel.
245
312
  def green(g1)
246
313
  Rubyvis.rgb(r,g1,b,a)
247
314
  end
315
+ # Constructs a new RGB color with the same red, green and alpha channels
316
+ # as this color, with the specified blue channel.
248
317
  def blue(b1)
249
318
  Rubyvis.rgb(r,g,b1,a)
250
319
  end
320
+ # Constructs a new RGB color with the same red, green and blue channels as this
321
+ # color, with the specified alpha channel.
322
+
251
323
  def alpha(a1)
252
324
  Rubyvis.rgb(r,g,b,a1)
253
325
  end
254
-
326
+ # Returns the RGB color equivalent to this color. This method is abstract and must be implemented by subclasses.
255
327
  def rgb
256
328
  self
257
329
  end
258
- def darker(*arguments)
259
- k,dummy=arguments
260
- k = 0.7 ** ( arguments.size>0 ? k : 1)
261
- return Rubyvis.rgb(
262
- [0, (k * self.r).floor].max,
263
- [0, (k * self.g).floor].max,
264
- [0, (k * self.b).floor].max,
265
- self.a)
330
+ # Returns a new color that is a brighter version of this color. This method
331
+ # applies an arbitrary scale factor to each of the three RGB components of this
332
+ # color to create a brighter version of this color. Although brighter and
333
+ # darker are inverse operations, the results of a series of invocations of
334
+ # these two methods might be inconsistent because of rounding errors.
335
+ def lighter(k=1)
336
+ k = 0.7**k
337
+ i = 30
338
+ r=self.r
339
+ g=self.g
340
+ b=self.b
341
+ return Rubyvis.rgb(i, i, i, a) if (!r and !g and !b)
342
+ r = i if (r and (r < i))
343
+ g = i if (g and (g < i))
344
+ b = i if (b and (b < i))
345
+ Rubyvis.rgb(
346
+ [255, (r/k).floor].min,
347
+ [255, (g/k).floor].min,
348
+ [255, (b/k).floor].min,
349
+ a)
350
+ end
351
+ # Returns a new color that is a darker version of this color. This method
352
+ # applies an arbitrary scale factor to each of the three RGB components of this
353
+ # color to create a darker version of this color. Although brighter and darker
354
+ # are inverse operations, the results of a series of invocations of these two
355
+ # methods might be inconsistent because of rounding errors.
356
+ def darker(k=1)
357
+ k = 0.7 ** k
358
+ Rubyvis.rgb(
359
+ [0, (k * r).floor].max,
360
+ [0, (k * g).floor].max,
361
+ [0, (k * b).floor].max,
362
+ a)
266
363
  end
364
+
267
365
  def to_s
268
366
  @color
269
367
  end
270
368
  end
369
+ # Represents a color in HSL space.
370
+ class Hsl < Color
371
+
372
+ # The hue, an integer in [0, 360].
373
+ attr_accessor :h
374
+ # The saturation, a float in [0, 1].
375
+ attr_accessor :s
376
+ # The lightness, a float in [0, 1].
377
+ attr_accessor :l
378
+ # The opacity, a float in [0, 1].
379
+ attr_accessor :a
380
+
381
+ def initialize(h,s,l,a)
382
+ c="hsl(#{h},#{s * 100}%,#{l * 100}%)"
383
+ super(c,a)
384
+ @h=h
385
+ @s=s
386
+ @l=l
387
+ @a=a
388
+ end
389
+
390
+ # Returns the RGB color equivalent to this HSL color.
391
+ def rgb
392
+ h = self.h
393
+ s = self.s
394
+ l = self.l
395
+
396
+ # Some simple corrections for h, s and l. */
397
+ h = h % 360
398
+ h += 360 if (h < 0)
399
+ s = [0, [s, 1].min].max
400
+ l = [0, [l, 1].min].max
401
+
402
+ # From FvD 13.37, CSS Color Module Level 3
403
+ m2 = (l <= 0.5) ? (l * (1 + s)) : (l + s - l * s)
404
+ m1 = 2 * l - m2
405
+ v=lambda {|h1|
406
+ if (h1 > 360)
407
+ h1 -= 360;
408
+ elsif (h1 < 0)
409
+ h1 += 360
410
+ end
411
+
412
+
413
+ return m1 + (m2 - m1) * h1 / 60 if (h1 < 60)
414
+ return m2 if (h1 < 180)
415
+ return m1 + (m2 - m1) * (240 - h1) / 60 if (h1 < 240)
416
+ return m1
417
+ }
418
+ vv=lambda {|h1|
419
+ (v(h1) * 255).round
420
+ }
421
+
422
+ Rubyvis.rgb(vv.call(h + 120), vv.call(h), vv.call(h - 120), a)
423
+ end
424
+ end
425
+
426
+
427
+
271
428
  end
272
429
  end