rubyvis 0.3.6 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. data.tar.gz.sig +0 -0
  2. data/History.txt +16 -0
  3. data/Manifest.txt +61 -0
  4. data/README.txt +9 -7
  5. data/Rakefile +1 -1
  6. data/lib/rubyvis.rb +3 -17
  7. data/lib/rubyvis/color/color.rb +11 -13
  8. data/lib/rubyvis/flatten.rb +5 -7
  9. data/lib/rubyvis/layout/stack.rb +15 -10
  10. data/lib/rubyvis/mark.rb +10 -2
  11. data/lib/rubyvis/mark/area.rb +5 -3
  12. data/lib/rubyvis/mark/line.rb +4 -3
  13. data/lib/rubyvis/mark/panel.rb +8 -3
  14. data/lib/rubyvis/mark/rule.rb +1 -0
  15. data/lib/rubyvis/scene/svg_area.rb +17 -17
  16. data/lib/rubyvis/scene/svg_curve.rb +8 -5
  17. data/lib/rubyvis/scene/svg_line.rb +32 -29
  18. data/lib/rubyvis/scene/svg_scene.rb +3 -5
  19. data/lib/rubyvis/scene/svg_wedge.rb +4 -3
  20. data/lib/rubyvis/vector.rb +104 -0
  21. data/spec/anchor_spec.rb +29 -0
  22. data/spec/area_spec.rb +83 -0
  23. data/spec/bar_spec.rb +3 -0
  24. data/spec/color_spec.rb +13 -1
  25. data/spec/dot_spec.rb +41 -0
  26. data/spec/fixtures/anchor.html +25 -0
  27. data/spec/fixtures/anchor.svg +1 -0
  28. data/spec/fixtures/area-segmented.html +29 -0
  29. data/spec/fixtures/area_interpolation.html +66 -0
  30. data/spec/fixtures/area_interpolation.svg +1 -0
  31. data/spec/fixtures/area_segmented.svg +1 -0
  32. data/spec/fixtures/dot-anchor.html +33 -0
  33. data/spec/fixtures/dot_anchor.svg +1 -0
  34. data/spec/fixtures/layers.js +28 -0
  35. data/spec/fixtures/layout_arc.svg +1 -0
  36. data/spec/fixtures/layout_cluster.html +39 -0
  37. data/spec/fixtures/layout_cluster.svg +1 -0
  38. data/spec/fixtures/layout_cluster_left_group_2.html +39 -0
  39. data/spec/fixtures/layout_cluster_left_group_2.svg +1 -0
  40. data/spec/fixtures/layout_grid.html +34 -0
  41. data/spec/fixtures/layout_grid.svg +1 -0
  42. data/spec/fixtures/layout_horizon.svg +24 -0
  43. data/spec/fixtures/layout_indent.html +39 -0
  44. data/spec/fixtures/layout_indent.svg +1 -0
  45. data/spec/fixtures/layout_matrix.svg +1 -0
  46. data/spec/fixtures/layout_pack.html +38 -0
  47. data/spec/fixtures/layout_pack.svg +1 -0
  48. data/spec/fixtures/layout_partition_fill.html +40 -0
  49. data/spec/fixtures/layout_partition_fill.svg +32 -0
  50. data/spec/fixtures/layout_tree_orient_left.html +36 -0
  51. data/spec/fixtures/layout_tree_orient_left.svg +1 -0
  52. data/spec/fixtures/layout_tree_orient_radial_breadth_20.html +39 -0
  53. data/spec/fixtures/layout_tree_orient_radial_breadth_20.svg +1 -0
  54. data/spec/fixtures/layout_tree_orient_top.svg +1 -0
  55. data/spec/fixtures/layout_treemap.svg +1 -0
  56. data/spec/fixtures/line_interpolation.html +63 -0
  57. data/spec/fixtures/line_interpolation.svg +1 -0
  58. data/spec/fixtures/line_interpolation_segmented.html +65 -0
  59. data/spec/fixtures/line_interpolation_segmented.svg +1 -0
  60. data/spec/fixtures/protovis-r3.3.js +287 -0
  61. data/spec/fixtures/rule-anchor.html +33 -0
  62. data/spec/fixtures/rule_anchor.svg +1 -0
  63. data/spec/fixtures/stack-expand.html +41 -0
  64. data/spec/fixtures/stack-silohouette.html +41 -0
  65. data/spec/fixtures/stack-wiggle.html +41 -0
  66. data/spec/fixtures/stack_expand.svg +1 -0
  67. data/spec/fixtures/stack_silohouette.svg +1 -0
  68. data/spec/fixtures/stack_wiggle.svg +1 -0
  69. data/spec/fixtures/svgscene.html +26 -0
  70. data/spec/fixtures/wedge-anchor.html +33 -0
  71. data/spec/fixtures/wedge-donut.html +35 -0
  72. data/spec/fixtures/wedge_anchor.svg +1 -0
  73. data/spec/fixtures/wedge_donut.svg +1 -0
  74. data/spec/flatten_spec.rb +47 -0
  75. data/spec/layout_arc_spec.rb +7 -26
  76. data/spec/layout_cluster_spec.rb +52 -0
  77. data/spec/layout_grid_spec.rb +40 -0
  78. data/spec/layout_horizon_spec.rb +6 -25
  79. data/spec/layout_indent_spec.rb +53 -0
  80. data/spec/layout_matrix_spec.rb +25 -52
  81. data/spec/layout_pack_spec.rb +49 -0
  82. data/spec/layout_partition_spec.rb +45 -0
  83. data/spec/layout_stack_spec.rb +60 -0
  84. data/spec/layout_tree_spec.rb +56 -0
  85. data/spec/layout_treemap_spec.rb +41 -0
  86. data/spec/line_spec.rb +118 -0
  87. data/spec/mark_spec.rb +4 -0
  88. data/spec/panel_spec.rb +12 -1
  89. data/spec/rule_spec.rb +34 -0
  90. data/spec/spec_helper.rb +158 -3
  91. data/spec/vector_spec.rb +36 -0
  92. data/spec/wedge_spec.rb +66 -0
  93. metadata +67 -14
  94. metadata.gz.sig +0 -0
@@ -67,13 +67,15 @@ module Rubyvis
67
67
 
68
68
  def area_bind
69
69
  mark_bind
70
- binds = self.binds
71
70
 
71
+ binds = self.binds
72
72
  required = binds.required
73
73
  optional = binds.optional
74
+
74
75
  optional.size.times {|i|
75
76
  prop = optional[i]
76
- prop.fixed = fixed.include? prop.name
77
+ prop.fixed = fixed.keys.include? prop.name
78
+
77
79
  if (prop.name == "segmented")
78
80
  required.push(prop)
79
81
  end
@@ -95,7 +97,7 @@ module Rubyvis
95
97
  }).tension(lambda {
96
98
  self.scene.target[self.index].tension
97
99
  })
98
- return anchor
100
+ anchor
99
101
  end
100
102
  end
101
103
 
@@ -7,12 +7,13 @@ module Rubyvis
7
7
  module LinePrototype # :nodoc:
8
8
  include AreaPrototype
9
9
  def line_anchor(name)
10
+
10
11
  anchor=area_anchor(name).text_align(lambda {|d|
11
- {'left'=>'right','bottom'=>'center', 'top'=>'center','center'=>'center','right'=>'left'}[self.name]
12
+ {'left'=>'right', 'bottom'=>'center', 'top'=>'center', 'center'=>'center','right'=>'left'}[self.name()]
12
13
  }).text_baseline(lambda{|d|
13
- {'top'=>'bottom', 'right'=>'middle', 'left'=>'middle','center'=>'middle','bottom'=>'top'}[self.name]
14
+ {'top'=>'bottom', 'right'=>'middle', 'left'=>'middle','center'=>'middle', 'bottom'=>'top'}[self.name()]
14
15
  })
15
- return anchor
16
+ anchor
16
17
  end
17
18
  end
18
19
 
@@ -96,18 +96,23 @@ module Rubyvis
96
96
  end
97
97
  if s.width.nil?
98
98
  w=Rubyvis.css(c,'width')
99
- s.width=w-s.left-s.right
99
+ s.width=w - s.left - s.right
100
100
  end
101
101
  if s.height.nil?
102
102
  w=Rubyvis.css(c,'height')
103
- s.height=h-s.top-s.bottom
103
+ s.height=h - s.top - s.bottom
104
104
  end
105
105
 
106
106
  else
107
107
  @_canvas||={}
108
108
  cache=@_canvas
109
109
  if(!(c=cache[self.index]))
110
- c=cache[self.index]=Rubyvis.document.add_element('span')
110
+ document=REXML::Document.new
111
+ document.add_element("document")
112
+ cache[self.index]=document.root
113
+ c=cache[self.index]
114
+
115
+ #c=cache[self.index]=Rubyvis.document.add_element('span')
111
116
  end
112
117
  end
113
118
  s.canvas=c
@@ -10,6 +10,7 @@ module Rubyvis
10
10
  def self.defaults
11
11
  Rule.new.mark_extend(Mark.defaults).line_width(1).stroke_style('black').antialias(false)
12
12
  end
13
+
13
14
  def type
14
15
  'rule'
15
16
  end
@@ -4,7 +4,7 @@ module Rubyvis
4
4
  e = scenes._g.elements[1]
5
5
  return e if scenes.size==0
6
6
  s=scenes[0]
7
- # segmented
7
+ # segmented
8
8
  return self.area_segment(scenes) if (s.segmented)
9
9
  # visible
10
10
  return e if (!s.visible)
@@ -63,8 +63,8 @@ module Rubyvis
63
63
  }
64
64
 
65
65
  if (s.interpolate == "basis")
66
- pathT = Rubyvis::SvgScene.curve_basis(pointsT);
67
- pathB = Rubyvis::SvgScene.curve_basis(pointsB);
66
+ pathT = Rubyvis::SvgScene.curve_basis(pointsT)
67
+ pathB = Rubyvis::SvgScene.curve_basis(pointsB)
68
68
  elsif (s.interpolate == "cardinal")
69
69
  pathT = Rubyvis::SvgScene.curve_cardinal(pointsT, s.tension);
70
70
  pathB = Rubyvis::SvgScene.curve_cardinal(pointsB, s.tension);
@@ -127,12 +127,10 @@ module Rubyvis
127
127
  end
128
128
 
129
129
  def self.area_segment(scenes)
130
-
131
130
  e = scenes._g.elements[1]
132
131
  s = scenes[0]
133
- pathsT=[]
134
- pathsB=[]
135
-
132
+ pathsT=nil
133
+ pathsB=nil
136
134
  if (s.interpolate == "basis" or s.interpolate == "cardinal" or s.interpolate == "monotone")
137
135
  pointsT = []
138
136
  pointsB = []
@@ -144,16 +142,17 @@ module Rubyvis
144
142
  }
145
143
 
146
144
  if (s.interpolate == "basis")
147
- pathT = Rubyvis.SvgScene.curve_basis_segments(pointsT);
148
- pathB = Rubyvis.SvgScene.curve_basis_segments(pointsB);
149
- elsif (s.interpolate == "cardinal")
150
- pathT = Rubyvis.SvgScene.curve_cardinal_segments(pointsT, s.tension);
151
- pathB = Rubyvis.SvgScene.curve_cardinal_segments(pointsB, s.tension);
145
+ pathsT = Rubyvis::SvgScene.curve_basis_segments(pointsT)
146
+ pathsB = Rubyvis::SvgScene.curve_basis_segments(pointsB)
147
+ elsif (s.interpolate == "cardinal")
148
+ pathsT = Rubyvis::SvgScene.curve_cardinal_segments(pointsT, s.tension);
149
+ pathsB = Rubyvis::SvgScene.curve_cardinal_segments(pointsB, s.tension);
152
150
  elsif # monotone
153
- pathT = Rubyvis.SvgScene.curve_monotone_segments(pointsT);
154
- pathB = Rubyvis.SvgScene.curve_monotone_segments(pointsB);
151
+ pathsT = Rubyvis::SvgScene.curve_monotone_segments(pointsT)
152
+ pathsB = Rubyvis::SvgScene.curve_monotone_segments(pointsB)
155
153
  end
156
154
  end
155
+
157
156
  n=scenes.size-1
158
157
  n.times {|i|
159
158
 
@@ -163,9 +162,10 @@ module Rubyvis
163
162
  # /* visible */
164
163
  next if (!s1.visible or !s2.visible)
165
164
 
166
- fill = s.fill_style
167
- stroke = s.stroke_style
168
- next e if (fill.opacity==0 and stroke.opacity==0)
165
+ fill = s1.fill_style
166
+ stroke = s1.stroke_style
167
+ next if (fill.opacity==0 and stroke.opacity==0)
168
+
169
169
  d=nil
170
170
  if (pathsT)
171
171
  pathT = pathsT[i]
@@ -102,7 +102,7 @@ module Rubyvis::SvgScene
102
102
  p1 = p2;
103
103
  p2 = p3;
104
104
  p3 = points[2];
105
- paths.push(firstPath + self.path_basis(p0, p1, p2, p3)); # merge first & second path
105
+ paths.push(firstPath + self.path_basis(p0, p1, p2, p3).to_s) # merge first & second path
106
106
  3.upto(points.size-1) {|i|
107
107
  p0 = p1;
108
108
  p1 = p2;
@@ -112,7 +112,7 @@ module Rubyvis::SvgScene
112
112
  }
113
113
 
114
114
  # merge last & second-to-last path
115
- paths.push(path_basis(p1, p2, p3, p3).segment + path_basis(p2, p3, p3, p3))
115
+ paths.push(path_basis(p1, p2, p3, p3).segment + path_basis(p2, p3, p3, p3).to_s)
116
116
  paths
117
117
  end
118
118
 
@@ -258,11 +258,14 @@ module Rubyvis::SvgScene
258
258
  d = []
259
259
  m = []
260
260
  dx = []
261
+ k=0
261
262
 
262
263
  #/* Compute the slopes of the secant lines between successive points. */
263
- (points.size-1).times {|k|
264
+
265
+ while(k < points.size-1) do
264
266
  d[k] = (points[k+1].top - points[k].top) / (points[k+1].left - points[k].left).to_f
265
- }
267
+ k+=1
268
+ end
266
269
 
267
270
  #/* Initialize the tangents at every point as the average of the secants. */
268
271
  m[0] = d[0]
@@ -320,7 +323,7 @@ module Rubyvis::SvgScene
320
323
  # * @param points the array of points.
321
324
  #/
322
325
  def self.curve_monotone_segments(points)
323
- return "" if (points.length <= 2)
326
+ return "" if (points.size <= 2)
324
327
  self.curve_hermite_segments(points, self.monotone_tangents(points))
325
328
  end
326
329
 
@@ -15,7 +15,7 @@ module Rubyvis
15
15
  return e if (fill.opacity==0.0 and stroke.opacity==0.0)
16
16
  #/* points */
17
17
 
18
- d = "M" + s.left.to_s + "," + s.top.to_s
18
+ d = "M#{s.left},#{s.top}"
19
19
 
20
20
  if (scenes.size > 2 and (['basis', 'cardinal', 'monotone'].include? s.interpolate))
21
21
  case (s.interpolate)
@@ -55,37 +55,40 @@ module Rubyvis
55
55
  s = scenes[0];
56
56
  paths=nil
57
57
  case s.interpolate
58
- when "basis"
59
- paths = curve_basis_segments(scenes)
60
- when "cardinal"
61
- paths=curve_cardinal_segments(scenes, s.tension)
62
- when "monotone"
63
- paths = curve_monotone_segments(scenes)
58
+ when "basis"
59
+ paths = curve_basis_segments(scenes)
60
+ when "cardinal"
61
+ paths=curve_cardinal_segments(scenes, s.tension)
62
+ when "monotone"
63
+ paths = curve_monotone_segments(scenes)
64
64
  end
65
65
 
66
- (scenes.length-1).times {|i|
66
+ (0...(scenes.size-1)).each {|i|
67
67
 
68
68
  s1 = scenes[i]
69
69
  s2 = scenes[i + 1];
70
-
70
+ #p "#{s1.top} #{s1.left} #{s1.line_width} #{s1.interpolate} #{s1.line_join}"
71
71
  # visible
72
- next if (!s1.visible and !s2.visible)
72
+ next if (!s1.visible or !s2.visible)
73
73
 
74
74
  stroke = s1.stroke_style
75
- fill = Rubyvis.Color.transparent
75
+ fill = Rubyvis::Color.transparent
76
76
 
77
77
  next if stroke.opacity==0.0
78
78
 
79
79
  # interpolate
80
80
  d=nil
81
- if ((s1.interpolate == "linear") and (s1.lineJoin == "miter"))
82
- fill = stroke;
83
- stroke = Rubyvis.Color.transparent;
84
- d = path_join(scenes[i - 1], s1, s2, scenes[i + 2]);
81
+ if ((s1.interpolate == "linear") and (s1.line_join == "miter"))
82
+ fill = stroke
83
+ stroke = Rubyvis::Color.transparent
84
+ s0=((i-1) < 0) ? nil : scenes[i-1]
85
+ s3=((i+2) >= scenes.size) ? nil : scenes[i+2]
86
+
87
+ d = path_join(s0, s1, s2, s3)
85
88
  elsif(paths)
86
89
  d = paths[i]
87
90
  else
88
- d = "M" + s1.left + "," + s1.top + path_segment(s1, s2);
91
+ d = "M#{s1.left},#{s1.top}#{path_segment(s1, s2)}"
89
92
  end
90
93
 
91
94
  e = SvgScene.expect(e, "path", {
@@ -102,7 +105,7 @@ module Rubyvis
102
105
  });
103
106
  e = SvgScene.append(e, scenes, i);
104
107
  }
105
- return e
108
+ e
106
109
  end
107
110
 
108
111
  # Returns the path segment for the specified points. */
@@ -148,17 +151,16 @@ module Rubyvis
148
151
 
149
152
  p2 = Rubyvis.vector(s2.left, s2.top)
150
153
 
151
- p = p2.minus(p1)
152
-
153
- v = p.perp().norm()
154
+ _p = p2.minus(p1)
154
155
 
155
- w = v.times(s1.lineWidth / (2 * this.scale))
156
+ v = _p.perp().norm()
157
+
158
+ w = v.times(s1.line_width / (2.0 * self.scale))
156
159
 
157
160
  a = p1.plus(w)
158
161
  b = p2.plus(w)
159
162
  c = p2.minus(w)
160
163
  d = p1.minus(w)
161
-
162
164
  #/*
163
165
  # * Start join. P0 is the previous line segment's start point. We define the
164
166
  # * cutting plane as the average of the vector perpendicular to P0-P1, and
@@ -167,19 +169,20 @@ module Rubyvis
167
169
  # * Note that we don't implement miter limits, so these can get wild.
168
170
  # */
169
171
  if (s0 and s0.visible)
170
- v1 = p1.minus(s0.left, s0.top).perp().norm().plus(v);
171
- d = line_intersect(p1, v1, d, p);
172
- a = line_intersect(p1, v1, a, p);
172
+ v1 = p1.minus(s0.left, s0.top).perp().norm().plus(v)
173
+ d = line_intersect(p1, v1, d, _p)
174
+ a = line_intersect(p1, v1, a, _p)
173
175
  end
174
176
 
175
177
  #/* Similarly, for end join. */
176
- if (s3 && s3.visible)
178
+ if (s3 and s3.visible)
177
179
  v2 = Rubyvis.vector(s3.left, s3.top).minus(p2).perp().norm().plus(v);
178
- c = line_intersect(p2, v2, c, p);
179
- b = line_intersect(p2, v2, b, p);
180
+ c = line_intersect(p2, v2, c, _p);
181
+ b = line_intersect(p2, v2, b, _p);
180
182
  end
181
183
 
182
- return "M" + a.x + "," + a.y+ "L" + b.x + "," + b.y+ " " + c.x + "," + c.y+ " " + d.x + "," + d.y
184
+ d="M#{a.x},#{a.y}L#{b.x},#{b.y} #{c.x},#{c.y} #{d.x},#{d.y}"
185
+ d
183
186
  end
184
187
  end
185
188
  end
@@ -9,7 +9,7 @@ require 'rubyvis/scene/svg_wedge'
9
9
  require 'rubyvis/scene/svg_image'
10
10
  require 'rubyvis/scene/svg_curve'
11
11
 
12
- class REXML::Element # :nodoc:
12
+ class REXML::Element #:nodoc:
13
13
  attr_accessor :_scene
14
14
  end
15
15
 
@@ -58,7 +58,6 @@ module Rubyvis
58
58
 
59
59
  {:svg=>svg,:css=>css}
60
60
  end
61
-
62
61
  def self.update_all(scenes)
63
62
  puts "update_all: #{scenes.inspect}" if $DEBUG
64
63
  if (scenes.size>0 and scenes[0].reverse and scenes.type!='line' and scenes.type!='area')
@@ -85,12 +84,11 @@ module Rubyvis
85
84
 
86
85
  def self.append(e,scenes,index)
87
86
  e._scene=OpenStruct.new({:scenes=>scenes, :index=>index})
88
- e=self.title(e,scenes[index])
89
-
87
+ e=self.title(e, scenes[index])
90
88
  if(!e.parent)
91
89
  scenes._g.add_element(e)
92
90
  end
93
- return e.next_sibling_node
91
+ e.next_sibling_node
94
92
  end
95
93
 
96
94
  # Applies a title tooltip to the specified element <tt>e</tt>, using the
@@ -11,11 +11,12 @@ module Rubyvis
11
11
 
12
12
  r1 = s.inner_radius
13
13
  r2 = s.outer_radius
14
+
14
15
  a = (s.angle).abs
15
16
  _p=nil
16
17
 
17
18
  if (a >= 2 * Math::PI)
18
- if (r1)
19
+ if (r1!=0)
19
20
  _p = "M0,#{r2 }A#{r2},#{r2} 0 1,1 0,#{-r2}A#{r2 },#{r2 } 0 1,1 0,#{r2}M0,#{r1}A#{r1},#{r1} 0 1,1 0,#{-r1}A#{r1},#{r1} 0 1,1 0,#{r1 }Z"
20
21
  else
21
22
  _p = "M0,#{r2}A#{r2},#{r2} 0 1,1 0,#{-r2}A#{r2},#{r2} 0 1,1 0,#{r2 }Z"
@@ -27,10 +28,10 @@ module Rubyvis
27
28
  c2 = Math.cos(ea)
28
29
  s1 = Math.sin(sa)
29
30
  s2 = Math.sin(ea)
30
- if (r1)
31
+ if (r1!=0)
31
32
  _p = "M#{r2 * c1},#{r2 * s1}A#{r2},#{r2} 0 #{((a < Math::PI) ? "0" : "1")},1 #{r2 * c2},#{r2 * s2}L#{r1 * c2},#{r1 * s2}A#{r1},#{r1} 0 #{((a < Math::PI) ? "0" : "1")},0 #{r1 * c1},#{r1 * s1}Z"
32
33
  else
33
- _p = "M#{r2 * c1},#{r2 * s1}A#{r2},#{r2} 0 #{((a < Math.PI) ? "0" : "1")},1 #{r2 * c2},#{r2 * s2}L0,0Z"
34
+ _p = "M#{r2 * c1},#{r2 * s1}A#{r2},#{r2} 0 #{((a < Math::PI) ? "0" : "1")},1 #{r2 * c2},#{r2 * s2}L0,0Z"
34
35
  end
35
36
  end
36
37
 
@@ -0,0 +1,104 @@
1
+ module Rubyvis
2
+ # Returns a {@link pv.Vector} for the specified <i>x</i> and <i>y</i>
3
+ # coordinate. This is a convenience factory method, equivalent to <tt>new
4
+ # pv.Vector(x, y)</tt>.
5
+ #
6
+ # @see pv.Vector
7
+ # @param {number} x the <i>x</i> coordinate.
8
+ # @param {number} y the <i>y</i> coordinate.
9
+ # @returns {pv.Vector} a vector for the specified coordinates.
10
+
11
+ def self.vector(x,y)
12
+ Rubyvis::Vector.new(x,y)
13
+ end
14
+ class Vector
15
+ attr_accessor :x,:y
16
+ # Constructs a {@link pv.Vector} for the specified <i>x</i> and <i>y</i>
17
+ # coordinate. This constructor should not be invoked directly; use
18
+ # {@link pv.vector} instead.
19
+ #
20
+ # @class Represents a two-dimensional vector; a 2-tuple <i>&#x27e8;x,
21
+ # y&#x27e9;</i>. The intent of this class is to simplify vector math. Note that
22
+ # in performance-sensitive cases it may be more efficient to represent 2D
23
+ # vectors as simple objects with <tt>x</tt> and <tt>y</tt> attributes, rather
24
+ # than using instances of this class.
25
+ #
26
+ # @param {number} x the <i>x</i> coordinate.
27
+ # @param {number} y the <i>y</i> coordinate.
28
+ def initialize(x,y)
29
+ @x=x
30
+ @y=y
31
+ end
32
+ def ==(v)
33
+ @x==v.x and @y==v.y
34
+ end
35
+ # Returns a vector perpendicular to this vector: <i>&#x27e8;-y, x&#x27e9;</i>.
36
+ #
37
+ # @returns {pv.Vector} a perpendicular vector.
38
+ #/
39
+ def perp
40
+ Rubyvis::Vector.new(-@y,@x)
41
+ end
42
+ # Returns a normalized copy of this vector: a vector with the same direction,
43
+ # but unit length. If this vector has zero length this method returns a copy of
44
+ # this vector.
45
+ #
46
+ # @returns {pv.Vector} a unit vector.
47
+ def norm
48
+ l=length()
49
+ times(l!=0 ? (1.0 / l) : 1.0)
50
+ end
51
+
52
+ # Returns the magnitude of this vector, defined as <i>sqrt(x * x + y * y)</i>.
53
+ #
54
+ # @returns {number} a length.
55
+ def length
56
+ Math.sqrt(@x**2 + @y**2)
57
+ end
58
+
59
+ # Returns a scaled copy of this vector: <i>&#x27e8;x * k, y * k&#x27e9;</i>.
60
+ # To perform the equivalent divide operation, use <i>1 / k</i>.
61
+ #
62
+ # @param {number} k the scale factor.
63
+ # @returns {pv.Vector} a scaled vector.
64
+ def times(k)
65
+ Rubyvis::Vector.new(@x * k, @y * k)
66
+ end
67
+ # Returns this vector plus the vector <i>v</i>: <i>&#x27e8;x + v.x, y +
68
+ # v.y&#x27e9;</i>. If only one argument is specified, it is interpreted as the
69
+ # vector <i>v</i>.
70
+ #
71
+ # @param {number} x the <i>x</i> coordinate to add.
72
+ # @param {number} y the <i>y</i> coordinate to add.
73
+ # @returns {pv.Vector} a new vector.
74
+ def plus(x,y=nil)
75
+
76
+ return (y.nil?) ? Rubyvis::Vector.new(@x + x.x, @y + x.y) : Rubyvis::Vector.new(@x + x, @y + y)
77
+ end
78
+
79
+ # Returns this vector minus the vector <i>v</i>: <i>&#x27e8;x - v.x, y -
80
+ # v.y&#x27e9;</i>. If only one argument is specified, it is interpreted as the
81
+ # vector <i>v</i>.
82
+ #
83
+ # @param {number} x the <i>x</i> coordinate to subtract.
84
+ # @param {number} y the <i>y</i> coordinate to subtract.
85
+ # @returns {pv.Vector} a new vector.
86
+
87
+ def minus(x,y=nil)
88
+
89
+ return (y.nil?) ? Rubyvis::Vector.new(@x - x.x, @y - x.y) : Rubyvis::Vector.new(@x - x, @y - y)
90
+ end
91
+
92
+ # Returns the dot product of this vector and the vector <i>v</i>: <i>x * v.x +
93
+ # y * v.y</i>. If only one argument is specified, it is interpreted as the
94
+ # vector <i>v</i>.
95
+ #
96
+ # @param {number} x the <i>x</i> coordinate to dot.
97
+ # @param {number} y the <i>y</i> coordinate to dot.
98
+ # @returns {number} a dot product.
99
+ def dot(x, y=nil)
100
+ (y.nil?) ? @x * x.x + @y * x.y : @x * x + @y * y
101
+ end
102
+ end
103
+ end
104
+