rubyvis 0.3.6 → 0.4.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.
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
+