geometry 6.4 → 6.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ruby.yml +21 -0
  3. data/Gemfile +3 -0
  4. data/README.markdown +1 -2
  5. data/geometry.gemspec +5 -1
  6. data/lib/geometry/annulus.rb +20 -2
  7. data/lib/geometry/arc.rb +72 -1
  8. data/lib/geometry/edge.rb +21 -4
  9. data/lib/geometry/line.rb +84 -18
  10. data/lib/geometry/obround.rb +1 -2
  11. data/lib/geometry/path.rb +27 -0
  12. data/lib/geometry/point.rb +59 -8
  13. data/lib/geometry/point_iso.rb +12 -2
  14. data/lib/geometry/point_one.rb +44 -34
  15. data/lib/geometry/point_zero.rb +12 -1
  16. data/lib/geometry/polygon.rb +13 -12
  17. data/lib/geometry/polyline.rb +6 -6
  18. data/lib/geometry/rectangle.rb +12 -12
  19. data/lib/geometry/rotation.rb +5 -3
  20. data/lib/geometry/size.rb +1 -3
  21. data/lib/geometry/square.rb +13 -11
  22. data/lib/geometry/transformation/composition.rb +1 -1
  23. data/lib/geometry/transformation.rb +15 -0
  24. data/lib/geometry/triangle.rb +1 -1
  25. data/test/geometry/annulus.rb +12 -0
  26. data/test/geometry/arc.rb +98 -0
  27. data/test/geometry/circle.rb +3 -3
  28. data/test/geometry/edge.rb +16 -2
  29. data/test/geometry/line.rb +73 -0
  30. data/test/geometry/path.rb +16 -0
  31. data/test/geometry/point.rb +78 -2
  32. data/test/geometry/point_iso.rb +31 -21
  33. data/test/geometry/point_one.rb +11 -1
  34. data/test/geometry/point_zero.rb +46 -36
  35. data/test/geometry/polygon.rb +1 -1
  36. data/test/geometry/rectangle.rb +6 -1
  37. data/test/geometry/rotation.rb +1 -1
  38. data/test/geometry/size_one.rb +1 -1
  39. data/test/geometry/size_zero.rb +1 -1
  40. data/test/geometry/square.rb +15 -10
  41. data/test/geometry/transformation.rb +15 -1
  42. data/test/geometry/vector.rb +1 -1
  43. metadata +36 -9
  44. data/.travis.yml +0 -12
@@ -134,6 +134,29 @@ describe Geometry::PointSlopeLine do
134
134
  line2.must_equal subject
135
135
  line3.wont_equal subject
136
136
  end
137
+
138
+ it 'must know how to be horizontal' do
139
+ Geometry::PointSlopeLine.new([1,2],0).horizontal?.must_equal true
140
+ Geometry::PointSlopeLine.new([1,2],1).horizontal?.must_equal false
141
+ end
142
+
143
+ it 'must know how to be vertical' do
144
+ Geometry::PointSlopeLine.new([1,2], Float::INFINITY).vertical?.must_equal true
145
+ Geometry::PointSlopeLine.new([1,2], -Float::INFINITY).vertical?.must_equal true
146
+ Geometry::PointSlopeLine.new([1,2],1).vertical?.must_equal false
147
+ end
148
+
149
+ it 'must have an x-intercept' do
150
+ subject.intercept(:x).must_equal 1
151
+ end
152
+
153
+ it 'must not have an x-intercept for horizontal lines' do
154
+ Geometry::PointSlopeLine.new([1,2], 0).intercept(:x).must_equal nil
155
+ end
156
+
157
+ it 'must have a y-intercept' do
158
+ subject.intercept.must_equal(-1)
159
+ end
137
160
  end
138
161
 
139
162
  describe Geometry::SlopeInterceptLine do
@@ -163,6 +186,29 @@ describe Geometry::SlopeInterceptLine do
163
186
  line2.must_equal subject
164
187
  line3.wont_equal subject
165
188
  end
189
+
190
+ it 'must know how to be horizontal' do
191
+ Geometry::SlopeInterceptLine.new(0, 2).horizontal?.must_equal true
192
+ Geometry::SlopeInterceptLine.new(1, 2).horizontal?.must_equal false
193
+ end
194
+
195
+ it 'must know how to be vertical' do
196
+ Geometry::SlopeInterceptLine.new(Float::INFINITY, 2).vertical?.must_equal true
197
+ Geometry::SlopeInterceptLine.new(-Float::INFINITY, 2).vertical?.must_equal true
198
+ Geometry::SlopeInterceptLine.new(1, 2).vertical?.must_equal false
199
+ end
200
+
201
+ it 'must have an x-intercept' do
202
+ subject.intercept(:x).must_equal(-2/3)
203
+ end
204
+
205
+ it 'must not have an x-intercept for horizontal lines' do
206
+ Geometry::SlopeInterceptLine.new(0, 2).intercept(:x).must_equal nil
207
+ end
208
+
209
+ it 'must have a y-intercept' do
210
+ subject.intercept.must_equal 2
211
+ end
166
212
  end
167
213
 
168
214
  describe Geometry::TwoPointLine do
@@ -192,4 +238,31 @@ describe Geometry::TwoPointLine do
192
238
  line2.must_equal subject
193
239
  line3.wont_equal subject
194
240
  end
241
+
242
+ it 'must know how to be horizontal' do
243
+ Geometry::TwoPointLine.new([1,2],[2,2]).horizontal?.must_equal true
244
+ Geometry::TwoPointLine.new([1,2],[3,4]).horizontal?.must_equal false
245
+ end
246
+
247
+ it 'must know how to be vertical' do
248
+ Geometry::TwoPointLine.new([1,2], [1,3]).vertical?.must_equal true
249
+ Geometry::TwoPointLine.new([1,2], [1,-3]).vertical?.must_equal true
250
+ Geometry::TwoPointLine.new([1,2],[3,4]).vertical?.must_equal false
251
+ end
252
+
253
+ it 'must have an x-intercept' do
254
+ subject.intercept(:x).must_equal(-1)
255
+ end
256
+
257
+ it 'must not have an x-intercept for horizontal lines' do
258
+ Geometry::TwoPointLine.new([1,2],[2,2]).intercept(:x).must_equal nil
259
+ end
260
+
261
+ it 'must have an x-intercept for vertical lines' do
262
+ Geometry::TwoPointLine.new([1,2], [1,3]).intercept(:x).must_equal 1
263
+ end
264
+
265
+ it 'must have a y-intercept' do
266
+ subject.intercept.must_equal 1
267
+ end
195
268
  end
@@ -63,4 +63,20 @@ describe Geometry::Path do
63
63
  path.elements[0].last.must_equal path.elements[1].first
64
64
  end
65
65
  end
66
+
67
+ describe 'attributes' do
68
+ let(:unit_square) { Geometry::Path.new [0,0], [1,0], [1,1], [0,1] }
69
+
70
+ it 'must know the max' do
71
+ unit_square.max.must_equal Point[1,1]
72
+ end
73
+
74
+ it 'must know the min' do
75
+ unit_square.min.must_equal Point[0,0]
76
+ end
77
+
78
+ it 'must know the min and the max' do
79
+ unit_square.minmax.must_equal [Point[0,0], Point[1,1]]
80
+ end
81
+ end
66
82
  end
@@ -2,6 +2,7 @@ require 'minitest/autorun'
2
2
  require 'geometry/point'
3
3
 
4
4
  describe Geometry::Point do
5
+ PointIso = Geometry::PointIso
5
6
  PointOne = Geometry::PointOne
6
7
  PointZero = Geometry::PointZero
7
8
 
@@ -14,6 +15,15 @@ describe Geometry::Point do
14
15
  Point.one(3).must_equal Point[1,1,1]
15
16
  end
16
17
 
18
+ it 'must generate a PointIso' do
19
+ Point.iso(3).must_be_kind_of(PointIso)
20
+ Point.iso(3).value.must_equal 3
21
+ end
22
+
23
+ it 'must generate a Point filled with a given value' do
24
+ Point.iso(3, 2).must_equal Point[3,3]
25
+ end
26
+
17
27
  it "must generate a PointZero" do
18
28
  Point.zero.must_be_instance_of(PointZero)
19
29
  end
@@ -114,7 +124,24 @@ describe Geometry::Point do
114
124
  Point[1,2].dup.must_equal Point[1,2]
115
125
  end
116
126
 
117
- describe 'minmax' do
127
+ it 'must pop' do
128
+ Point[1,2,3,4].pop.must_equal Point[4]
129
+ Point[1,2,3,4].pop(2).must_equal Point[3,4]
130
+ end
131
+
132
+ it 'must push' do
133
+ Point[1,2].push(3,4).must_equal Point[1,2,3,4]
134
+ end
135
+
136
+ it 'must shift' do
137
+ Point[1,2,3,4].shift.must_equal Point[1]
138
+ end
139
+
140
+ it 'must unshift' do
141
+ Point[2,3,4].unshift(1).must_equal Point[1,2,3,4]
142
+ end
143
+
144
+ describe 'minimum' do
118
145
  it 'must have a minimum' do
119
146
  Point[1,2].min.must_equal 1
120
147
  end
@@ -132,6 +159,20 @@ describe Geometry::Point do
132
159
  Point[1,3].min(4,2).must_equal Point[1,2]
133
160
  end
134
161
 
162
+ it 'must minimum with a PointIso' do
163
+ Point[-5,-5,5].min(PointIso.new(-5/2)).must_equal Point[-5,-5,-5/2]
164
+ end
165
+
166
+ it 'must minimum with a PointOne' do
167
+ Point[-5,-5,5].min(Point.one).must_equal Point[-5,-5,1]
168
+ end
169
+
170
+ it 'must minimum with a PointZero' do
171
+ Point[-5,-5,5].min(Point.zero).must_equal Point[-5,-5,0]
172
+ end
173
+ end
174
+
175
+ describe 'maximum' do
135
176
  it 'must have a maximum' do
136
177
  Point[1,2].max.must_equal 2
137
178
  end
@@ -149,6 +190,20 @@ describe Geometry::Point do
149
190
  Point[1,3].max(4,2).must_equal Point[4,3]
150
191
  end
151
192
 
193
+ it 'must maximum with a PointIso' do
194
+ Point[-5,-5,5].max(PointIso.new(-5/2)).must_equal Point[-5/2, -5/2, 5]
195
+ end
196
+
197
+ it 'must maximum with a PointOne' do
198
+ Point[-5,-5,5].max(Point.one).must_equal Point[1, 1, 5]
199
+ end
200
+
201
+ it 'must maximum with a PointZero' do
202
+ Point[-5,-5,5].max(Point.zero).must_equal Point[0, 0, 5]
203
+ end
204
+ end
205
+
206
+ describe 'minmax' do
152
207
  it 'must have a minmax' do
153
208
  Point[1,2].minmax.must_equal [1,2]
154
209
  end
@@ -161,9 +216,21 @@ describe Geometry::Point do
161
216
  Point[1,3].minmax([4,2]).must_equal [Point[1,2], Point[4,3]]
162
217
  end
163
218
 
164
- it 'must maximum with multiple arguments' do
219
+ it 'must minmax with multiple arguments' do
165
220
  Point[1,3].minmax(4,2).must_equal [Point[1,2], Point[4,3]]
166
221
  end
222
+
223
+ it 'must minmax with a PointIso' do
224
+ Point[-5,-5,5].minmax(PointIso.new(-5/2)).must_equal [Point[-5,-5,-5/2], Point[-5/2, -5/2, 5]]
225
+ end
226
+
227
+ it 'must minmax with a PointOne' do
228
+ Point[-5,-5,5].minmax(Point.one).must_equal [Point[-5,-5,1], Point[1, 1, 5]]
229
+ end
230
+
231
+ it 'must minmax with a PointZero' do
232
+ Point[-5,-5,5].minmax(Point.zero).must_equal [Point[-5,-5,0], Point[0, 0, 5]]
233
+ end
167
234
  end
168
235
 
169
236
  describe "arithmetic" do
@@ -254,6 +321,15 @@ describe Geometry::Point do
254
321
  end
255
322
  end
256
323
 
324
+ describe 'attributes' do
325
+ it 'must have a quadrant' do
326
+ Point[1,1].quadrant.must_equal 1
327
+ Point[-1,1].quadrant.must_equal 2
328
+ Point[-1,-1].quadrant.must_equal 3
329
+ Point[1,-1].quadrant.must_equal 4
330
+ end
331
+ end
332
+
257
333
  describe "coercion" do
258
334
  subject { Point[1,2] }
259
335
 
@@ -2,9 +2,19 @@ require 'minitest/autorun'
2
2
  require 'geometry/point_iso'
3
3
 
4
4
  describe Geometry::PointIso do
5
- let(:value) { 5 }
5
+ let(:iso_value) { 5 }
6
6
  subject { Geometry::PointIso.new(5) }
7
7
 
8
+ it 'must pop' do
9
+ subject.pop.must_equal Point[5]
10
+ subject.pop(2).must_equal Point[5, 5]
11
+ end
12
+
13
+ it 'must shift' do
14
+ subject.shift.must_equal Point[5]
15
+ subject.shift(2).must_equal Point[5, 5]
16
+ end
17
+
8
18
  describe 'minmax' do
9
19
  it 'must have a minimum' do
10
20
  subject.min.must_equal 5
@@ -73,30 +83,30 @@ describe Geometry::PointIso do
73
83
  end
74
84
 
75
85
  it 'must have +@' do
76
- (+subject).must_be :eql?, value
86
+ (+subject).must_be :eql?, iso_value
77
87
  (+subject).must_be_instance_of(Geometry::PointIso)
78
88
  end
79
89
 
80
90
  it 'must have unary negation' do
81
- (-subject).must_be :eql?, -value
91
+ (-subject).must_be :eql?, -iso_value
82
92
  (-subject).must_be_instance_of(Geometry::PointIso)
83
93
  end
84
94
 
85
95
  describe 'Accessors' do
86
96
  it 'must return 1 for array access' do
87
- subject[3].must_equal value
97
+ subject[3].must_equal iso_value
88
98
  end
89
99
 
90
100
  it 'must return 1 for named element access' do
91
- subject.x.must_equal value
92
- subject.y.must_equal value
93
- subject.z.must_equal value
101
+ subject.x.must_equal iso_value
102
+ subject.y.must_equal iso_value
103
+ subject.z.must_equal iso_value
94
104
  end
95
105
  end
96
106
 
97
107
  it 'must add a number' do
98
- (subject + 3).must_equal (value + 3)
99
- (3 + subject).must_equal (3 + value)
108
+ (subject + 3).must_equal (iso_value + 3)
109
+ (3 + subject).must_equal (3 + iso_value)
100
110
  end
101
111
 
102
112
  it 'return a Point when adding two Points' do
@@ -105,24 +115,24 @@ describe Geometry::PointIso do
105
115
  end
106
116
 
107
117
  it 'must return an Array when adding an array' do
108
- (subject + [5,6]).must_equal [value+5, value+6]
118
+ (subject + [5,6]).must_equal [iso_value+5, iso_value+6]
109
119
  # ([5,6] + subject).must_equal [10, 11]
110
120
  end
111
121
 
112
122
  it 'must return a Point when adding a Size' do
113
123
  (subject + Size[5,6]).must_be_instance_of(Point)
114
- (subject + Size[5,6]).must_equal Point[value+5, value+6]
124
+ (subject + Size[5,6]).must_equal Point[iso_value+5, iso_value+6]
115
125
  end
116
126
 
117
127
  describe 'when subtracting' do
118
128
  it 'must subtract a number' do
119
- (subject - 3).must_equal (value - 3)
120
- (3 - subject).must_equal -2
129
+ (subject - 3).must_equal (iso_value - 3)
130
+ (3 - subject).must_equal(-2)
121
131
  end
122
132
 
123
133
  it 'return a Point when subtracting two Points' do
124
- (subject - right).must_equal Point[value - right.x, value - right.y]
125
- (left - subject).must_equal Point[left.x - value, left.y - value]
134
+ (subject - right).must_equal Point[iso_value - right.x, iso_value - right.y]
135
+ (left - subject).must_equal Point[left.x - iso_value, left.y - iso_value]
126
136
  end
127
137
 
128
138
  it 'must return a Point when subtracting an array' do
@@ -221,15 +231,15 @@ describe Geometry::PointIso do
221
231
  end
222
232
 
223
233
  it 'must be equal to a Point of subjects' do
224
- subject.must_be :==, Point[value, value]
225
- subject.must_be :eql?, Point[value, value]
226
- subject.must_be :===, Point[value, value]
227
- Point[value, value].must_equal subject
228
- subject.must_equal Point[value, value]
234
+ subject.must_be :==, Point[iso_value, iso_value]
235
+ subject.must_be :eql?, Point[iso_value, iso_value]
236
+ subject.must_be :===, Point[iso_value, iso_value]
237
+ Point[iso_value, iso_value].must_equal subject
238
+ subject.must_equal Point[iso_value, iso_value]
229
239
  end
230
240
 
231
241
  it 'must be equal to an Vector of the same value' do
232
- subject.must_be :eql?, Vector[value, value]
242
+ subject.must_be :eql?, Vector[iso_value, iso_value]
233
243
  Vector[5, 5].must_equal subject
234
244
  end
235
245
 
@@ -5,6 +5,16 @@ describe Geometry::PointOne do
5
5
  subject { Geometry::PointOne.new }
6
6
  let(:one) { Geometry::PointOne.new }
7
7
 
8
+ it 'must pop' do
9
+ subject.pop.must_equal Point[1]
10
+ subject.pop(2).must_equal Point[1, 1]
11
+ end
12
+
13
+ it 'must shift' do
14
+ subject.shift.must_equal Point[1]
15
+ subject.shift(2).must_equal Point[1, 1]
16
+ end
17
+
8
18
  describe 'minmax' do
9
19
  it 'must have a minimum' do
10
20
  subject.min.must_equal 1
@@ -116,7 +126,7 @@ describe Geometry::PointOne do
116
126
 
117
127
  describe 'when subtracting' do
118
128
  it 'must subtract a number' do
119
- (one - 3).must_equal -2
129
+ (one - 3).must_equal(-2)
120
130
  (3 - one).must_equal 2
121
131
  end
122
132
 
@@ -5,55 +5,65 @@ describe Geometry::PointZero do
5
5
  subject { Geometry::PointZero.new }
6
6
  let(:zero) { Geometry::PointZero.new }
7
7
 
8
- describe 'minmax' do
9
- it 'must have a minimum' do
10
- subject.min.must_equal 0
8
+ it 'must pop' do
9
+ subject.pop.must_equal Point[0]
10
+ subject.pop(2).must_equal Point[0, 0]
11
11
  end
12
12
 
13
- it 'must minimum with another Point' do
14
- subject.min(Point[-1,7]).must_equal Point[-1,0]
13
+ it 'must shift' do
14
+ subject.shift.must_equal Point[0]
15
+ subject.shift(2).must_equal Point[0, 0]
15
16
  end
16
17
 
17
- it 'must minimum with an Array' do
18
- subject.min([-1,7]).must_equal Point[-1,0]
19
- end
18
+ describe 'minmax' do
19
+ it 'must have a minimum' do
20
+ subject.min.must_equal 0
21
+ end
20
22
 
21
- it 'must minimum with a multiple arguments' do
22
- subject.min(-1,7).must_equal Point[-1,0]
23
- end
23
+ it 'must minimum with another Point' do
24
+ subject.min(Point[-1,7]).must_equal Point[-1,0]
25
+ end
24
26
 
25
- it 'must have a maximum' do
26
- subject.max.must_equal 0
27
- end
27
+ it 'must minimum with an Array' do
28
+ subject.min([-1,7]).must_equal Point[-1,0]
29
+ end
28
30
 
29
- it 'must maximum with another Point' do
30
- subject.max(Point[7,-1]).must_equal Point[7,0]
31
- end
31
+ it 'must minimum with a multiple arguments' do
32
+ subject.min(-1,7).must_equal Point[-1,0]
33
+ end
32
34
 
33
- it 'must maximum with an Array' do
34
- subject.max([7,-1]).must_equal Point[7,0]
35
- end
35
+ it 'must have a maximum' do
36
+ subject.max.must_equal 0
37
+ end
36
38
 
37
- it 'must maximum with multiple arguments' do
38
- subject.max(7,-1).must_equal Point[7,0]
39
- end
39
+ it 'must maximum with another Point' do
40
+ subject.max(Point[7,-1]).must_equal Point[7,0]
41
+ end
40
42
 
41
- it 'must have a minmax' do
42
- subject.minmax.must_equal [0, 0]
43
- end
43
+ it 'must maximum with an Array' do
44
+ subject.max([7,-1]).must_equal Point[7,0]
45
+ end
44
46
 
45
- it 'must minmax with another Point' do
46
- subject.minmax(Point[7,-1]).must_equal [Point[0,-1], Point[7,0]]
47
- end
47
+ it 'must maximum with multiple arguments' do
48
+ subject.max(7,-1).must_equal Point[7,0]
49
+ end
48
50
 
49
- it 'must minmax with an Array' do
50
- subject.minmax([7,-1]).must_equal [Point[0,-1], Point[7,0]]
51
- end
51
+ it 'must have a minmax' do
52
+ subject.minmax.must_equal [0, 0]
53
+ end
52
54
 
53
- it 'must maximum with multiple arguments' do
54
- subject.minmax(7,-1).must_equal [Point[0,-1], Point[7,0]]
55
+ it 'must minmax with another Point' do
56
+ subject.minmax(Point[7,-1]).must_equal [Point[0,-1], Point[7,0]]
57
+ end
58
+
59
+ it 'must minmax with an Array' do
60
+ subject.minmax([7,-1]).must_equal [Point[0,-1], Point[7,0]]
61
+ end
62
+
63
+ it 'must maximum with multiple arguments' do
64
+ subject.minmax(7,-1).must_equal [Point[0,-1], Point[7,0]]
65
+ end
55
66
  end
56
- end
57
67
 
58
68
  describe "arithmetic" do
59
69
  let(:left) { Point[1,2] }
@@ -117,7 +127,7 @@ end
117
127
 
118
128
  describe "when subtracting" do
119
129
  it "must return a number" do
120
- (zero - 3).must_equal -3
130
+ (zero - 3).must_equal(-3)
121
131
  (3 - zero).must_equal 3
122
132
  end
123
133
 
@@ -118,7 +118,7 @@ describe Geometry::Polygon do
118
118
 
119
119
  describe "spaceship" do
120
120
  it "with a Point" do
121
- (unit_square <=> Point[2,0]).must_equal -1
121
+ (unit_square <=> Point[2,0]).must_equal(-1)
122
122
  (unit_square <=> Point[1,0]).must_equal 0
123
123
  (unit_square <=> Point[0.5,0.5]).must_equal 1
124
124
  end
@@ -133,10 +133,11 @@ describe Geometry::Rectangle do
133
133
  edges.each {|edge| assert_kind_of(Geometry::Edge, edge)}
134
134
  end
135
135
 
136
- it "have a points property that returns 4 points" do
136
+ it "have a points property that returns 4 points in clockwise order starting from the lower-left" do
137
137
  points = rectangle.points
138
138
  assert_equal(4, points.size)
139
139
  points.each {|point| assert_kind_of(Geometry::Point, point)}
140
+ points.must_equal [Point[1,2], Point[1,4], Point[3,4], Point[3,2]]
140
141
  end
141
142
 
142
143
  it "must have a bounds property that returns a Rectangle" do
@@ -154,5 +155,9 @@ describe Geometry::Rectangle do
154
155
  it "must have a min property that returns the lower left corner of the bounding rectangle" do
155
156
  subject.min.must_equal Point[1,2]
156
157
  end
158
+
159
+ it 'must have a path property that returns a closed Path' do
160
+ rectangle.path.must_equal Geometry::Path.new([1,2], [1,4], [3,4], [3,2], [1,2])
161
+ end
157
162
  end
158
163
  end
@@ -13,7 +13,7 @@ describe Geometry::Rotation do
13
13
  rotation.angle.must_equal Math::PI/2
14
14
  rotation.x.x.must_be_close_to 0
15
15
  rotation.x.y.must_be_close_to 1
16
- rotation.y.x.must_be_close_to -1
16
+ rotation.y.x.must_be_close_to(-1)
17
17
  rotation.y.y.must_be_close_to 0
18
18
  end
19
19
 
@@ -37,7 +37,7 @@ describe Geometry::SizeOne do
37
37
 
38
38
  describe 'when subtracting' do
39
39
  it 'must subtract a number' do
40
- (one - 3).must_equal -2
40
+ (one - 3).must_equal(-2)
41
41
  (3 - one).must_equal 2
42
42
  end
43
43
 
@@ -39,7 +39,7 @@ describe Geometry::SizeZero do
39
39
 
40
40
  describe "when subtracting" do
41
41
  it "must return a number" do
42
- (zero - 3).must_equal -3
42
+ (zero - 3).must_equal(-3)
43
43
  (3 - zero).must_equal 3
44
44
  end
45
45
 
@@ -9,7 +9,7 @@ describe Geometry::Square do
9
9
  square = Square.new from:[1,2], to:[3,4]
10
10
  square.must_be_kind_of Geometry::Square
11
11
  end
12
-
12
+
13
13
  it "must reorder swapped points when constructed from two Points" do
14
14
  square = Geometry::Square.new from:[3,4], to:[1,2]
15
15
  square.must_be_kind_of Geometry::Square
@@ -57,7 +57,7 @@ describe Geometry::Square do
57
57
  -> { Square.new size:[1,2] }.must_raise Geometry::NotSquareError
58
58
  end
59
59
  end
60
-
60
+
61
61
  describe "properties" do
62
62
  subject { Square.new from:[2,3], to:[3,4] }
63
63
 
@@ -66,7 +66,7 @@ describe Geometry::Square do
66
66
  end
67
67
 
68
68
  it 'must have edges' do
69
- subject.edges.must_equal [Edge([2,3], [3,3]), Edge.new([3,3], [3,4]), Edge.new([3,4], [2,4]), Edge.new([2,4], [2,3])]
69
+ subject.edges.must_equal [Edge([2,3], [2,4]), Edge.new([2,4], [3,4]), Edge.new([3,4], [3,3]), Edge.new([3,3], [2,3])]
70
70
  end
71
71
 
72
72
  it "must have an origin accessor" do
@@ -85,8 +85,13 @@ describe Geometry::Square do
85
85
  subject.min.must_equal Point[2, 3]
86
86
  end
87
87
 
88
- it 'must have points' do
89
- subject.points.must_equal [Point[2,3], Point[3,3], Point[3,4], Point[2,4]]
88
+ it 'have a points property that returns 4 points in clockwise order starting from the lower-left' do
89
+ subject.points.must_equal [Point[2,3], Point[2,4], Point[3,4], Point[3,3]]
90
+ end
91
+
92
+ it 'must have a path property that returns a closed Path' do
93
+ square = Geometry::Square.new origin:[0,0], size:5
94
+ square.path.must_equal Geometry::Path.new([0,0], [0,5], [5,5], [5,0], [0,0])
90
95
  end
91
96
  end
92
97
  end
@@ -102,13 +107,13 @@ describe Geometry::CenteredSquare do
102
107
 
103
108
  describe "properties" do
104
109
  let(:square) { Geometry::CenteredSquare.new [2,3], 4 }
105
-
110
+
106
111
  it "must have a center property" do
107
112
  square.center.must_equal Point[2,3]
108
113
  end
109
114
 
110
- it "must have a points property" do
111
- square.points.must_equal [Point[0,1], Point[4,1], Point[4,5], Point[0,5]]
115
+ it 'have a points property that returns 4 points in clockwise order starting from the lower-left' do
116
+ square.points.must_equal [Point[0,1], Point[0,5], Point[4,5], Point[4,1]]
112
117
  end
113
118
 
114
119
  it "must have a height property" do
@@ -149,8 +154,8 @@ describe Geometry::SizedSquare do
149
154
  square.center.must_equal Point[4,5]
150
155
  end
151
156
 
152
- it "must have a points property" do
153
- square.points.must_equal [Point[2,3], Point[6,3], Point[6,7], Point[2,7]]
157
+ it 'have a points property that returns 4 points in clockwise order starting from the lower-left' do
158
+ square.points.must_equal [Point[2,3], Point[2,7], Point[6,7], Point[6,3]]
154
159
  end
155
160
 
156
161
  it "must have a height property" do
@@ -78,12 +78,26 @@ describe Geometry::Transformation do
78
78
  rotation.angle.must_equal Math::PI/2
79
79
  rotation.x.x.must_be_close_to 0
80
80
  rotation.x.y.must_be_close_to 1
81
- rotation.y.x.must_be_close_to -1
81
+ rotation.y.x.must_be_close_to(-1)
82
82
  rotation.y.y.must_be_close_to 0
83
83
  end
84
84
  end
85
85
  end
86
86
 
87
+ describe 'convenience constructors' do
88
+ it 'must create a translation from coordinates' do
89
+ Geometry.translation(1, 2, 3).translation.must_equal Point[1,2,3]
90
+ end
91
+
92
+ it 'must create a translation from an Array' do
93
+ Geometry.translation([1, 2, 3]).translation.must_equal Point[1,2,3]
94
+ end
95
+
96
+ it 'must create a translation from a Point' do
97
+ Geometry.translation(Point[1, 2, 3]).translation.must_equal Point[1,2,3]
98
+ end
99
+ end
100
+
87
101
  it 'must translate with a Point' do
88
102
  Transformation.new(translate:[1,2]).translate(Point[3,4]).translation.must_equal Point[4,6]
89
103
  end
@@ -15,7 +15,7 @@ describe Vector do
15
15
  end
16
16
 
17
17
  it "must cross product" do
18
- left.cross(right).must_equal -2
18
+ left.cross(right).must_equal(-2)
19
19
  Vector[1,2,3].cross(Vector[3,4,5]).must_equal Vector[-2, 4, -2]
20
20
  (Vector[1,2,3] ** Vector[3,4,5]).must_equal Vector[-2, 4, -2]
21
21
  end