geometry-in-ruby 0.0.1

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 (51) hide show
  1. data/.gitignore +6 -0
  2. data/Gemfile +7 -0
  3. data/LICENSE +21 -0
  4. data/README.markdown +105 -0
  5. data/Rakefile +24 -0
  6. data/geometry-in-ruby.gemspec +23 -0
  7. data/lib/geometry/arc.rb +94 -0
  8. data/lib/geometry/circle.rb +122 -0
  9. data/lib/geometry/cluster_factory.rb +15 -0
  10. data/lib/geometry/edge.rb +140 -0
  11. data/lib/geometry/line.rb +154 -0
  12. data/lib/geometry/obround.rb +238 -0
  13. data/lib/geometry/path.rb +67 -0
  14. data/lib/geometry/point.rb +163 -0
  15. data/lib/geometry/point_zero.rb +107 -0
  16. data/lib/geometry/polygon.rb +368 -0
  17. data/lib/geometry/polyline.rb +318 -0
  18. data/lib/geometry/rectangle.rb +378 -0
  19. data/lib/geometry/regular_polygon.rb +136 -0
  20. data/lib/geometry/rotation.rb +190 -0
  21. data/lib/geometry/size.rb +75 -0
  22. data/lib/geometry/size_zero.rb +70 -0
  23. data/lib/geometry/square.rb +113 -0
  24. data/lib/geometry/text.rb +24 -0
  25. data/lib/geometry/transformation/composition.rb +39 -0
  26. data/lib/geometry/transformation.rb +171 -0
  27. data/lib/geometry/triangle.rb +78 -0
  28. data/lib/geometry/vector.rb +34 -0
  29. data/lib/geometry.rb +22 -0
  30. data/test/geometry/arc.rb +25 -0
  31. data/test/geometry/circle.rb +112 -0
  32. data/test/geometry/edge.rb +132 -0
  33. data/test/geometry/line.rb +132 -0
  34. data/test/geometry/obround.rb +25 -0
  35. data/test/geometry/path.rb +66 -0
  36. data/test/geometry/point.rb +258 -0
  37. data/test/geometry/point_zero.rb +177 -0
  38. data/test/geometry/polygon.rb +214 -0
  39. data/test/geometry/polyline.rb +266 -0
  40. data/test/geometry/rectangle.rb +154 -0
  41. data/test/geometry/regular_polygon.rb +120 -0
  42. data/test/geometry/rotation.rb +108 -0
  43. data/test/geometry/size.rb +97 -0
  44. data/test/geometry/size_zero.rb +153 -0
  45. data/test/geometry/square.rb +66 -0
  46. data/test/geometry/transformation/composition.rb +49 -0
  47. data/test/geometry/transformation.rb +169 -0
  48. data/test/geometry/triangle.rb +32 -0
  49. data/test/geometry/vector.rb +41 -0
  50. data/test/geometry.rb +5 -0
  51. metadata +117 -0
@@ -0,0 +1,132 @@
1
+ require 'minitest/autorun'
2
+ require 'geometry/line'
3
+
4
+ describe Geometry::Line do
5
+ Line = Geometry::Line
6
+ Point = Geometry::Point
7
+
8
+ describe "when initializing" do
9
+ it "must accept two named points" do
10
+ line = Line.new(from:Point[0,0], to:Point[10,10])
11
+ line.must_be_kind_of(Line)
12
+ line.must_be_instance_of(Geometry::TwoPointLine)
13
+ line.first.must_equal Point[0,0]
14
+ line.last.must_equal Point[10,10]
15
+ end
16
+
17
+ it "must accept named start and end points" do
18
+ line = Line.new(start:Point[0,0], end:Point[10,10])
19
+ line.must_be_kind_of(Line)
20
+ line.must_be_instance_of(Geometry::TwoPointLine)
21
+ line.first.must_equal Point[0,0]
22
+ line.last.must_equal Point[10,10]
23
+ end
24
+
25
+ it "must raise an exception when no arguments are given" do
26
+ -> { Line.new }.must_raise ArgumentError
27
+ end
28
+ end
29
+
30
+ it "create a Line object from 2 Points" do
31
+ line = Geometry::Line[Geometry::Point[0,0], Geometry::Point[10,10]]
32
+ assert_kind_of(Geometry::Line, line)
33
+ assert_kind_of(Geometry::TwoPointLine, line)
34
+ end
35
+ it "create a Line object from two arrays" do
36
+ line = Geometry::Line[[0,0], [10,10]]
37
+ assert(line.is_a?(Geometry::Line))
38
+ assert_kind_of(Geometry::TwoPointLine, line)
39
+ assert_kind_of(Geometry::Point, line.first)
40
+ assert_kind_of(Geometry::Point, line.last)
41
+ end
42
+ it "create a Line object from two Vectors" do
43
+ line = Geometry::Line[Vector[0,0], Vector[10,10]]
44
+ assert(line.is_a?(Geometry::Line))
45
+ assert_kind_of(Geometry::TwoPointLine, line)
46
+ end
47
+
48
+ it "create a Line from a slope and y-intercept" do
49
+ line = Geometry::Line[0.75, 5]
50
+ assert(line.is_a?(Geometry::Line))
51
+ assert_kind_of(Geometry::SlopeInterceptLine, line)
52
+ assert_equal(5, line.intercept)
53
+ assert_equal(0.75, line.slope)
54
+ end
55
+
56
+ it "create a Line from a Rational slope and y-intercept" do
57
+ line = Geometry::Line[Rational(3,4), 5]
58
+ assert_kind_of(Geometry::SlopeInterceptLine, line)
59
+ assert(line.is_a?(Geometry::Line))
60
+ assert_equal(Rational(3,4), line.slope)
61
+ end
62
+
63
+ it "have a special constructor for horizontal lines" do
64
+ line = Geometry::Line.horizontal
65
+ assert(line.horizontal?)
66
+ end
67
+ it "have a special constructor for vertical lines" do
68
+ line = Geometry::Line.vertical
69
+ assert(line.vertical?)
70
+ end
71
+
72
+ it "have accessor for y-intercept" do
73
+ line = Geometry::Line[0.75, 5]
74
+ assert_equal(5, line.intercept)
75
+ assert_equal(5, line.intercept(:y))
76
+ end
77
+ it "have accessor for x-intercept" do
78
+ line = Geometry::Line.vertical(7)
79
+ assert_equal(7, line.intercept(:x))
80
+ end
81
+
82
+ it "return the correct x-intercept for vertical lines" do
83
+ line = Geometry::Line.vertical(7)
84
+ assert_equal(7, line.intercept(:x))
85
+ end
86
+ it "return the correct y-intercept for horizontal lines" do
87
+ line = Geometry::Line.horizontal(4)
88
+ assert_equal(4, line.intercept(:y))
89
+ end
90
+
91
+ it "return nil x-intercept for horizontal lines" do
92
+ line = Geometry::Line.horizontal
93
+ assert_nil(line.intercept(:x))
94
+ end
95
+ it "return nil y-intercept for vertical lines" do
96
+ line = Geometry::Line.vertical
97
+ assert_nil(line.intercept(:y))
98
+ end
99
+
100
+ it "implement inspect" do
101
+ line = Geometry::Line[[0,0], [10,10]]
102
+ assert_equal('Line(Point[0, 0], Point[10, 10])', line.inspect)
103
+ end
104
+ it "implement to_s" do
105
+ line = Geometry::Line[[0,0], [10,10]]
106
+ assert_equal('Line(Point[0, 0], Point[10, 10])', line.to_s)
107
+ end
108
+ end
109
+
110
+ describe Geometry::PointSlopeLine do
111
+ subject { Geometry::PointSlopeLine.new [1,2], 3 }
112
+
113
+ it "must have a slope attribute" do
114
+ subject.slope.must_equal 3
115
+ end
116
+ end
117
+
118
+ describe Geometry::SlopeInterceptLine do
119
+ subject { Geometry::SlopeInterceptLine.new 3, 2 }
120
+
121
+ it "must have a slope attribute" do
122
+ subject.slope.must_equal 3
123
+ end
124
+ end
125
+
126
+ describe Geometry::TwoPointLine do
127
+ subject { Geometry::TwoPointLine.new [1,2], [3,4] }
128
+
129
+ it "must have a slope attribute" do
130
+ subject.slope.must_equal 1
131
+ end
132
+ end
@@ -0,0 +1,25 @@
1
+ require 'minitest/autorun'
2
+ require 'geometry/obround'
3
+
4
+ describe Geometry::Obround do
5
+ Obround = Geometry::Obround
6
+
7
+ describe "when constructed" do
8
+ it "must accept two Points" do
9
+ obround = Geometry::Obround.new [1,2], [3,4]
10
+ obround.must_be_kind_of Geometry::Obround
11
+ end
12
+
13
+ it "must accept a width and height" do
14
+ obround = Geometry::Obround.new 2, 3
15
+ obround.must_be_kind_of Geometry::Obround
16
+ obround.height.must_equal 3
17
+ obround.width.must_equal 2
18
+ end
19
+
20
+ it "must compare equal" do
21
+ obround = Geometry::Obround.new [1,2], [3,4]
22
+ obround.must_equal Obround.new([1,2], [3,4])
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,66 @@
1
+ require 'minitest/autorun'
2
+ require 'geometry/path'
3
+
4
+ describe Geometry::Path do
5
+ describe "construction" do
6
+ it "must create a Path with no arguments" do
7
+ path = Geometry::Path.new
8
+ path.must_be_kind_of Geometry::Path
9
+ path.elements.wont_be_nil
10
+ path.elements.size.must_equal 0
11
+ end
12
+
13
+ it "must create a Path from Points" do
14
+ path = Geometry::Path.new Point[1,1], Point[2,2], Point[3,3]
15
+ path.elements.size.must_equal 2
16
+ path.elements.each {|a| a.must_be_kind_of Geometry::Edge }
17
+ end
18
+
19
+ it "with connected Edges" do
20
+ path = Geometry::Path.new Edge.new([1,1], [2,2]), Edge.new([2,2], [3,3])
21
+ path.elements.size.must_equal 2
22
+ path.elements.each {|a| a.must_be_kind_of Geometry::Edge }
23
+ end
24
+
25
+ it "with disjoint Edges" do
26
+ path = Geometry::Path.new Edge.new([1,1], [2,2]), Edge.new([3,3], [4,4])
27
+ path.elements.size.must_equal 3
28
+ path.elements.each {|a| a.must_be_kind_of Geometry::Edge }
29
+ end
30
+
31
+ it "with Points and Arcs" do
32
+ path = Geometry::Path.new [0,0], [1.0,0.0], Arc.new(center:[1,1], radius:1, start:-90*Math::PI/180, end:0), [2.0,1.0], [1,2]
33
+ path.elements.size.must_equal 3
34
+ path.elements[0].must_be_kind_of Geometry::Edge
35
+ path.elements[1].must_be_kind_of Geometry::Arc
36
+ path.elements[2].must_be_kind_of Geometry::Edge
37
+ end
38
+
39
+ it "with Edges and Arcs" do
40
+ path = Geometry::Path.new Edge.new([0,0], [1.0,0.0]), Arc.new(center:[1,1], radius:1, start:-90*Math::PI/180, end:0), Edge.new([2.0,1.0], [1,2])
41
+ path.elements.size.must_equal 3
42
+ path.elements[0].must_be_kind_of Geometry::Edge
43
+ path.elements[1].must_be_kind_of Geometry::Arc
44
+ path.elements[2].must_be_kind_of Geometry::Edge
45
+ end
46
+
47
+ it "with disjoint Edges and Arcs" do
48
+ path = Geometry::Path.new Edge.new([0,0], [1,0]), Arc.new(center:[2,1], radius:1, start:-90*Math::PI/180, end:0), Edge.new([3,1], [1,2])
49
+ path.elements.size.must_equal 4
50
+ path.elements[0].must_be_kind_of Geometry::Edge
51
+ path.elements[1].must_be_kind_of Geometry::Edge
52
+ path.elements[2].must_be_kind_of Geometry::Arc
53
+ path.elements[3].must_be_kind_of Geometry::Edge
54
+ end
55
+
56
+ it "with disjoint Arcs" do
57
+ path = Geometry::Path.new Arc.new(center:[2,1], radius:1, start:-90*Math::PI/180, end:0), Arc.new(center:[3,1], radius:1, start:-90*Math::PI/180, end:0)
58
+ path.elements.size.must_equal 3
59
+ path.elements[0].must_be_kind_of Geometry::Arc
60
+ path.elements[1].must_be_kind_of Geometry::Edge
61
+ path.elements[2].must_be_kind_of Geometry::Arc
62
+
63
+ path.elements[0].last.must_equal path.elements[1].first
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,258 @@
1
+ require 'minitest/autorun'
2
+ require 'geometry/point'
3
+
4
+ describe Geometry::Point do
5
+ PointZero = Geometry::PointZero
6
+
7
+ describe "class methods" do
8
+ it "must generate a PointZero" do
9
+ Point.zero.must_be_instance_of(PointZero)
10
+ end
11
+
12
+ it "must generate a Point full of zeros" do
13
+ Point.zero(3).must_equal Point[0,0,0]
14
+ end
15
+ end
16
+
17
+ describe "constructor" do
18
+ it "must return the Point when constructed from a Point" do
19
+ original_point = Point[3,4]
20
+ point = Geometry::Point[original_point]
21
+ point.must_be_same_as original_point
22
+ point.size.must_equal 2
23
+ point.x.must_equal 3
24
+ point.y.must_equal 4
25
+ end
26
+
27
+ it "must return the PointZero when constructed from a PointZero" do
28
+ original_point = Geometry::PointZero.new
29
+ point = Geometry::Point[original_point]
30
+ point.must_be_same_as original_point
31
+ end
32
+ end
33
+
34
+ it "create a Point object from an array" do
35
+ point = Geometry::Point[[3,4]]
36
+ assert_equal(2, point.size)
37
+ assert_equal(3, point.x)
38
+ assert_equal(4, point.y)
39
+ end
40
+ it "create a Point object from individual parameters" do
41
+ point = Geometry::Point[3,4]
42
+ assert_equal(2, point.size)
43
+ assert_equal(3, point.x)
44
+ assert_equal(4, point.y)
45
+ end
46
+ it "create a Point object from a Vector" do
47
+ point = Geometry::Point[Vector[3,4]]
48
+ assert_equal(2, point.size)
49
+ assert_equal(3, point.x)
50
+ assert_equal(4, point.y)
51
+ end
52
+
53
+ it "create a Point object from a Point using list syntax" do
54
+ point = Geometry::Point[Geometry::Point[13,14]]
55
+ assert_equal(2, point.size)
56
+ assert_equal(13, point.x)
57
+ assert_equal(14, point.y)
58
+ end
59
+ it "allow indexed element access" do
60
+ point = Geometry::Point[5,6]
61
+ assert_equal(2, point.size)
62
+ assert_equal(5, point[0])
63
+ assert_equal(6, point[1])
64
+ end
65
+ it "allow named element access" do
66
+ point = Geometry::Point[5,6,7]
67
+ assert_equal(3, point.size)
68
+ assert_equal(5, point.x)
69
+ assert_equal(6, point.y)
70
+ assert_equal(7, point.z)
71
+ end
72
+
73
+ it "implement inspect" do
74
+ point = Geometry::Point[8,9]
75
+ assert_equal('Point[8, 9]', point.inspect)
76
+ end
77
+ it "implement to_s" do
78
+ point = Geometry::Point[10,11]
79
+ assert_equal('Point[10, 11]', point.to_s)
80
+ end
81
+
82
+ it "must support array access" do
83
+ Point[1,2][0].must_equal 1
84
+ Point[1,2][1].must_equal 2
85
+ Point[1,2][2].must_equal nil
86
+ end
87
+
88
+ it "must clone" do
89
+ Point[1,2].clone.must_be_instance_of(Point)
90
+ Point[1,2].clone.must_equal Point[1,2]
91
+ end
92
+
93
+ it "must duplicate" do
94
+ Point[1,2].dup.must_be_instance_of(Point)
95
+ Point[1,2].dup.must_equal Point[1,2]
96
+ end
97
+
98
+ describe "arithmetic" do
99
+ let(:left) { Point[1,2] }
100
+ let(:right) { Point[3,4] }
101
+
102
+ it "must have +@" do
103
+ (+left).must_equal Point[1,2]
104
+ (+left).must_be_instance_of(Point)
105
+ end
106
+
107
+ it "must have unary negation" do
108
+ (-left).must_equal Point[-1,-2]
109
+ (-left).must_be_instance_of(Point)
110
+ end
111
+
112
+ describe "when adding" do
113
+ it "return a Point when adding two Points" do
114
+ assert_kind_of(Point, left+right)
115
+ end
116
+
117
+ it "must return a Point when adding an array to a Point" do
118
+ (left + [5,6]).must_equal Point[6,8]
119
+ end
120
+
121
+ it "must add a Numeric to all elements" do
122
+ (left + 2).must_equal Point[3,4]
123
+ (2 + left).must_equal Point[3,4]
124
+ end
125
+
126
+ it "must raise an exception when adding mismatched sizes" do
127
+ lambda { left + [1,2,3,4] }.must_raise Geometry::DimensionMismatch
128
+ end
129
+
130
+ it "must return a Point when adding a Vector" do
131
+ (left + Vector[5,6]).must_equal Point[6,8]
132
+ (Vector[5,6] + right).must_equal Vector[8,10]
133
+ end
134
+
135
+ it "must return self when adding a PointZero" do
136
+ (left + Point.zero).must_equal left
137
+ end
138
+
139
+ it "must return self when adding a NilClass" do
140
+ (left + nil).must_equal left
141
+ end
142
+ end
143
+
144
+ describe "when subtracting" do
145
+ it "return a Point when subtracting two Points" do
146
+ assert_kind_of(Point, left-right)
147
+ end
148
+
149
+ it "must return a Point when subtracting an array from a Point" do
150
+ (left - [5,6]).must_equal Point[-4, -4]
151
+ end
152
+
153
+ it "must subtract a Numeric from all elements" do
154
+ (left - 2).must_equal Point[-1, 0]
155
+ (2 - left).must_equal Point[1,0]
156
+ end
157
+
158
+ it "must raise an exception when subtracting mismatched sizes" do
159
+ lambda { left - [1,2,3,4] }.must_raise Geometry::DimensionMismatch
160
+ end
161
+
162
+ it "must return self when subtracting a PointZero" do
163
+ (left - Point.zero).must_equal left
164
+ end
165
+
166
+ it "must return self when subtracting a NilClass" do
167
+ (left - nil).must_equal left
168
+ end
169
+ end
170
+
171
+ describe "when multiplying" do
172
+ it "must return a Point when multiplied by a Matrix" do
173
+ (Matrix[[1,2],[3,4]]*Point[5,6]).must_equal Point[17, 39]
174
+ end
175
+ end
176
+ end
177
+
178
+ describe "coercion" do
179
+ subject { Point[1,2] }
180
+
181
+ it "must coerce Arrays into Points" do
182
+ subject.coerce([3,4]).must_equal [Point[3,4], subject]
183
+ end
184
+
185
+ it "must coerce Vectors into Points" do
186
+ subject.coerce(Vector[3,4]).must_equal [Point[3,4], subject]
187
+ end
188
+
189
+ it "must coerce a Numeric into a Point" do
190
+ subject.coerce(42).must_equal [Point[42,42], subject]
191
+ end
192
+
193
+ it "must reject anything that can't be coerced" do
194
+ -> { subject.coerce(NilClass) }.must_raise TypeError
195
+ end
196
+ end
197
+
198
+ describe "comparison" do
199
+ let(:point) { Point[1,2] }
200
+
201
+ it "must compare equal to an equal Array" do
202
+ point.must_be :==, [1,2]
203
+ point.must_be :eql?, [1,2]
204
+ [1,2].must_equal point
205
+ end
206
+
207
+ it "must not compare equal to an unequal Array" do
208
+ point.wont_equal [3,2]
209
+ [3,2].wont_equal point
210
+ end
211
+
212
+ it "must compare equal to an equal Point" do
213
+ point.must_be :==, Point[1,2]
214
+ point.must_be :eql?, Point[1,2]
215
+ Point[1,2].must_equal point
216
+ end
217
+
218
+ it "must not compare equal to an unequal Point" do
219
+ point.wont_equal Point[3,2]
220
+ Point[3,2].wont_equal point
221
+ end
222
+
223
+ it "must compare equal to an equal Vector" do
224
+ point.must_equal Vector[1,2]
225
+ Vector[1,2].must_equal point
226
+ end
227
+
228
+ it "must not compare equal to an unequal Vector" do
229
+ point.wont_equal Vector[3,2]
230
+ Vector[3,2].wont_equal point
231
+ end
232
+
233
+ it "must think that floats == ints" do
234
+ Point[1,2].must_be :==, Point[1.0,2.0]
235
+ Point[1.0,2.0].must_be :==, Point[1,2]
236
+ end
237
+
238
+ it "must not think that floats eql? ints" do
239
+ Point[1,2].wont_be :eql?, Point[1.0,2.0]
240
+ Point[1.0,2.0].wont_be :eql?, Point[1,2]
241
+ end
242
+
243
+ describe "spaceship" do
244
+ it "must spaceship with another Point of the same length" do
245
+ (Point[1,2] <=> Point[0,3]).must_equal Point[1,-1]
246
+ end
247
+
248
+ it "must spaceship with another Point of different length" do
249
+ (Point[1,2] <=> Point[0,3,4]).must_equal Point[1,-1]
250
+ (Point[1,2,4] <=> Point[0,3]).must_equal Point[1,-1]
251
+ end
252
+
253
+ it "must spaceship with an Array" do
254
+ (Point[1,2] <=> [0,3]).must_equal Point[1,-1]
255
+ end
256
+ end
257
+ end
258
+ end
@@ -0,0 +1,177 @@
1
+ require 'minitest/autorun'
2
+ require 'geometry/point_zero'
3
+
4
+ describe Geometry::PointZero do
5
+ let(:zero) { Geometry::PointZero.new }
6
+
7
+ describe "arithmetic" do
8
+ let(:left) { Point[1,2] }
9
+ let(:right) { Point[3,4] }
10
+
11
+ it "must have +@" do
12
+ (+zero).must_be :eql?, 0
13
+ (+zero).must_be_instance_of(Geometry::PointZero)
14
+ end
15
+
16
+ it "must have unary negation" do
17
+ (-zero).must_be :eql?, 0
18
+ (-zero).must_be_instance_of(Geometry::PointZero)
19
+ end
20
+
21
+ describe "Accessors" do
22
+ it "must return 0 for array access" do
23
+ zero[3].must_equal 0
24
+ end
25
+
26
+ it "must return 0 for named element access" do
27
+ zero.x.must_equal 0
28
+ zero.y.must_equal 0
29
+ zero.z.must_equal 0
30
+ end
31
+ end
32
+
33
+ describe "when adding" do
34
+ it "must return a number" do
35
+ (zero + 3).must_equal 3
36
+ (3 + zero).must_equal 3
37
+ end
38
+
39
+ it "return a Point when adding two Points" do
40
+ (zero + right).must_be_kind_of Point
41
+ (left + zero).must_be_kind_of Point
42
+ end
43
+
44
+ it "must return an Array when adding an array" do
45
+ (zero + [5,6]).must_equal [5,6]
46
+ # ([5,6] + zero).must_equal [5,6]
47
+ end
48
+
49
+ it "must return a Point when adding a Size" do
50
+ (zero + Size[5,6]).must_be_instance_of(Point)
51
+ (zero + Size[5,6]).must_equal Point[5,6]
52
+ end
53
+ end
54
+
55
+ describe "when subtracting" do
56
+ it "must return a number" do
57
+ (zero - 3).must_equal -3
58
+ (3 - zero).must_equal 3
59
+ end
60
+
61
+ it "return a Point when subtracting two Points" do
62
+ (zero - right).must_equal Point[-3,-4]
63
+ (left - zero).must_equal Point[1,2]
64
+ end
65
+
66
+ it "must return a Point when subtracting an array" do
67
+ (zero - [5,6]).must_equal [-5, -6]
68
+ # ([5,6] - zero).must_equal [5,6]
69
+ end
70
+
71
+ it "must return a Point when subtracting a Size" do
72
+ (zero - Size[5,6]).must_be_instance_of(Point)
73
+ (zero - Size[5,6]).must_equal Point[-5,-6]
74
+ end
75
+ end
76
+
77
+ describe "multiplication" do
78
+ it "must return 0 for scalars" do
79
+ (zero * 3).must_equal 0
80
+ (zero * 3.0).must_equal 0.0
81
+ end
82
+
83
+ it "must return 0 for Points" do
84
+ (zero * Point[1,2]).must_equal 0
85
+ end
86
+
87
+ it "must return 0 for Vectors" do
88
+ (zero * Vector[2,3]).must_equal 0
89
+ end
90
+ end
91
+
92
+ describe "division" do
93
+ it "must return 0 for non-zero scalars" do
94
+ (zero / 3).must_equal 0
95
+ (zero / 4.0).must_equal 0
96
+ end
97
+
98
+ it "must raise an exception when divided by 0" do
99
+ lambda { zero / 0 }.must_raise ZeroDivisionError
100
+ end
101
+
102
+ it "must raise an exception for Points" do
103
+ lambda { zero / Point[1,2] }.must_raise Geometry::OperationNotDefined
104
+ end
105
+
106
+ it "must raise an exception for Vectors" do
107
+ lambda { zero / Vector[1,2] }.must_raise Geometry::OperationNotDefined
108
+ end
109
+
110
+ end
111
+
112
+ end
113
+
114
+ describe "coercion" do
115
+ it "must coerce Arrays into Points" do
116
+ zero.coerce([3,4]).must_equal [Point[3,4], Point[0,0]]
117
+ end
118
+
119
+ it "must coerce Vectors into Vectors" do
120
+ zero.coerce(Vector[3,4]).must_equal [Vector[3,4], Vector[0,0]]
121
+ end
122
+
123
+ it "must coerce Points into Points" do
124
+ zero.coerce(Point[5,6]).must_equal [Point[5,6], Point[0,0]]
125
+ end
126
+ end
127
+
128
+ describe "comparison" do
129
+ subject { Geometry::PointZero.new }
130
+
131
+ it "must be equal to 0 and 0.0" do
132
+ zero.must_be :eql?, 0
133
+ zero.must_be :eql?, 0.0
134
+ end
135
+
136
+ it "must not be equal to a non-zero number" do
137
+ 1.wont_equal zero
138
+ 3.14.wont_equal zero
139
+ end
140
+
141
+ it "must be equal to an Array of zeros" do
142
+ zero.must_be :==, [0,0]
143
+ zero.must_be :eql?, [0,0]
144
+ zero.must_be :===, [0,0]
145
+ [0,0].must_equal zero
146
+ subject.must_equal [0,0]
147
+ end
148
+
149
+ it "must not be equal to a non-zero Array" do
150
+ zero.wont_equal [3,2]
151
+ [3,2].wont_equal zero
152
+ end
153
+
154
+ it "must be equal to a Point at the origin" do
155
+ zero.must_be :==, Point[0,0]
156
+ zero.must_be :eql?, Point[0,0]
157
+ zero.must_be :===, Point[0,0]
158
+ Point[0,0].must_equal zero
159
+ subject.must_equal Point[0,0]
160
+ end
161
+
162
+ it "must not be equal to a Point not at the origin" do
163
+ zero.wont_equal Point[3,2]
164
+ Point[3,2].wont_equal zero
165
+ end
166
+
167
+ it "must be equal to an Vector of zeroes" do
168
+ zero.must_be :eql?, Vector[0,0]
169
+ Vector[0,0].must_equal zero
170
+ end
171
+
172
+ it "must not be equal to a non-zero Vector" do
173
+ zero.wont_equal Vector[3,2]
174
+ Vector[3,2].wont_equal zero
175
+ end
176
+ end
177
+ end