geometry 6.2 → 6.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,199 @@
1
+ require 'minitest/autorun'
2
+ require 'geometry/point_one'
3
+
4
+ describe Geometry::PointOne do
5
+ subject { Geometry::PointOne.new }
6
+ let(:one) { Geometry::PointOne.new }
7
+
8
+ describe 'arithmetic' do
9
+ let(:left) { Point[1,2] }
10
+ let(:right) { Point[3,4] }
11
+
12
+ it 'must pretend to be a Point' do
13
+ subject.is_a?(Point).must_equal true
14
+ subject.kind_of?(Point).must_equal true
15
+
16
+ subject.is_a?(Geometry::PointOne).must_equal true
17
+ subject.kind_of?(Geometry::PointOne).must_equal true
18
+
19
+ subject.instance_of?(Point).must_equal false
20
+ subject.instance_of?(Geometry::PointOne).must_equal true
21
+ end
22
+
23
+ it 'must have +@' do
24
+ (+one).must_be :eql?, 1
25
+ (+one).must_be_instance_of(Geometry::PointOne)
26
+ end
27
+
28
+ it 'must have unary negation' do
29
+ (-one).must_be :eql?, -1
30
+ # (-one).must_be_instance_of(Geometry::PointOne)
31
+ end
32
+
33
+ describe 'Accessors' do
34
+ it 'must return 1 for array access' do
35
+ one[3].must_equal 1
36
+ end
37
+
38
+ it 'must return 1 for named element access' do
39
+ one.x.must_equal 1
40
+ one.y.must_equal 1
41
+ one.z.must_equal 1
42
+ end
43
+ end
44
+
45
+ it 'must add a number' do
46
+ (one + 3).must_equal 4
47
+ (3 + one).must_equal 4
48
+ end
49
+
50
+ it 'return a Point when adding two Points' do
51
+ (one + right).must_be_kind_of Point
52
+ (left + one).must_be_kind_of Point
53
+ end
54
+
55
+ it 'must return an Array when adding an array' do
56
+ (one + [5,6]).must_equal [6, 7]
57
+ ([5,6] + one).must_equal [5,6]
58
+ end
59
+
60
+ it 'must return a Point when adding a Size' do
61
+ (one + Size[5,6]).must_be_instance_of(Point)
62
+ (one + Size[5,6]).must_equal Point[6,7]
63
+ end
64
+
65
+ describe 'when subtracting' do
66
+ it 'must subtract a number' do
67
+ (one - 3).must_equal -2
68
+ (3 - one).must_equal 2
69
+ end
70
+
71
+ it 'return a Point when subtracting two Points' do
72
+ (one - right).must_equal Point[-2, -3]
73
+ (left - one).must_equal Point[0, 1]
74
+ end
75
+
76
+ it 'must return a Point when subtracting an array' do
77
+ (one - [5,6]).must_equal [-4, -5]
78
+ # ([5,6] - one).must_equal [4,5]
79
+ end
80
+
81
+ it 'must return a Point when subtracting a Size' do
82
+ (one - Size[5,6]).must_be_instance_of(Point)
83
+ (one - Size[5,6]).must_equal Point[-4,-5]
84
+ end
85
+ end
86
+
87
+ it 'must multiply by a scalar' do
88
+ (one * 3).must_equal 3
89
+ (one * 3.0).must_equal 3.0
90
+ end
91
+
92
+ it 'must refuse to multiply by a Point' do
93
+ -> { one * Point[1, 2] }.must_raise Geometry::OperationNotDefined
94
+ end
95
+
96
+ it 'must refuse to multiply by a Vector' do
97
+ -> { one * Vector[2, 3] }.must_raise Geometry::OperationNotDefined
98
+ end
99
+
100
+ it 'must divide by a scalar' do
101
+ (one / 3).must_equal 1/3
102
+ (one / 4.0).must_equal 1/4.0
103
+ end
104
+
105
+ it 'must raise an exception when divided by 0' do
106
+ -> { one / 0 }.must_raise ZeroDivisionError
107
+ end
108
+
109
+ describe 'division' do
110
+ it 'must raise an exception for Points' do
111
+ lambda { one / Point[1,2] }.must_raise Geometry::OperationNotDefined
112
+ end
113
+
114
+ it 'must raise an exception for Vectors' do
115
+ lambda { one / Vector[1,2] }.must_raise Geometry::OperationNotDefined
116
+ end
117
+ end
118
+ end
119
+
120
+ describe 'coercion' do
121
+ it 'must coerce Arrays into Points' do
122
+ one.coerce([3,4]).must_equal [Point[3,4], Point[1, 1]]
123
+ end
124
+
125
+ it 'must coerce Vectors into Vectors' do
126
+ one.coerce(Vector[3,4]).must_equal [Vector[3,4], Vector[1, 1]]
127
+ end
128
+
129
+ it 'must coerce Points into Points' do
130
+ one.coerce(Point[5,6]).must_equal [Point[5,6], Point[1, 1]]
131
+ end
132
+ end
133
+
134
+ describe 'comparison' do
135
+ subject { Geometry::PointOne.new }
136
+
137
+ it 'must be equal to 1 and 1.0' do
138
+ one.must_be :eql?, 1
139
+ one.must_be :eql?, 1.0
140
+ end
141
+
142
+ it 'must not be equal to a non-one number' do
143
+ 0.wont_equal one
144
+ 3.14.wont_equal one
145
+ end
146
+
147
+ it 'must be equal to an Array of ones' do
148
+ one.must_be :==, [1,1]
149
+ one.must_be :eql?, [1,1]
150
+ one.must_be :===, [1,1]
151
+ [1, 1].must_equal one
152
+ one.must_equal [1, 1]
153
+ end
154
+
155
+ it 'must not be equal to a non-one Array' do
156
+ one.wont_equal [3, 2, 1]
157
+ [3, 2, 1].wont_equal one
158
+ end
159
+
160
+ it 'must not be equal to a Point at the origin' do
161
+ one.wont_be :==, Point[0,0]
162
+ one.wont_be :eql?, Point[0,0]
163
+ one.wont_be :===, Point[0,0]
164
+ Point[0,0].wont_equal one
165
+ subject.wont_equal Point[0,0]
166
+ end
167
+
168
+ it 'must not be equal to a Point not at the origin' do
169
+ one.wont_equal Point[3,2]
170
+ Point[3,2].wont_equal one
171
+ end
172
+
173
+ it 'must be equal to a Point of ones' do
174
+ one.must_be :==, Point[1,1]
175
+ one.must_be :eql?, Point[1,1]
176
+ one.must_be :===, Point[1,1]
177
+ Point[1,1].must_equal one
178
+ one.must_equal Point[1,1]
179
+ end
180
+
181
+ it 'must be equal to an Vector of ones' do
182
+ one.must_be :eql?, Vector[1, 1]
183
+ Vector[1, 1].must_equal one
184
+ end
185
+
186
+ it 'must not be equal to a non-one Vector' do
187
+ one.wont_equal Vector[3,2]
188
+ Vector[3,2].wont_equal one
189
+ end
190
+ end
191
+
192
+ describe 'when enumerating' do
193
+ it 'must have a first method' do
194
+ one.first.must_equal 1
195
+ one.first(1).must_equal [1]
196
+ one.first(5).must_equal [1,1,1,1,1]
197
+ end
198
+ end
199
+ end
@@ -2,12 +2,24 @@ require 'minitest/autorun'
2
2
  require 'geometry/point_zero'
3
3
 
4
4
  describe Geometry::PointZero do
5
+ subject { Geometry::PointZero.new }
5
6
  let(:zero) { Geometry::PointZero.new }
6
7
 
7
8
  describe "arithmetic" do
8
9
  let(:left) { Point[1,2] }
9
10
  let(:right) { Point[3,4] }
10
-
11
+
12
+ it 'must pretend to be a Point' do
13
+ subject.is_a?(Point).must_equal true
14
+ subject.kind_of?(Point).must_equal true
15
+
16
+ subject.is_a?(PointZero).must_equal true
17
+ subject.kind_of?(PointZero).must_equal true
18
+
19
+ subject.instance_of?(Point).must_equal false
20
+ subject.instance_of?(PointZero).must_equal true
21
+ end
22
+
11
23
  it "must have +@" do
12
24
  (+zero).must_be :eql?, 0
13
25
  (+zero).must_be_instance_of(Geometry::PointZero)
@@ -31,8 +43,9 @@ describe Geometry::PointZero do
31
43
  end
32
44
 
33
45
  describe "when adding" do
34
- it "must return a number" do
46
+ it "must return a PointIso when adding a number" do
35
47
  (zero + 3).must_equal 3
48
+ (zero + 3).must_be_instance_of Geometry::PointIso
36
49
  (3 + zero).must_equal 3
37
50
  end
38
51
 
@@ -174,4 +187,12 @@ describe Geometry::PointZero do
174
187
  Vector[3,2].wont_equal zero
175
188
  end
176
189
  end
190
+
191
+ describe 'when enumerating' do
192
+ it 'must have a first method' do
193
+ subject.first.must_equal 0
194
+ subject.first(1).must_equal [0]
195
+ subject.first(5).must_equal [0,0,0,0,0]
196
+ end
197
+ end
177
198
  end
@@ -22,6 +22,10 @@ describe Geometry::Polyline do
22
22
  polyline.vertices.count.must_equal 4
23
23
  end
24
24
 
25
+ it 'must have a points attribute' do
26
+ unit_square.points.must_equal [Point[0,0], Point[1,0], Point[1,1], Point[0,1]]
27
+ end
28
+
25
29
  it 'must know the max' do
26
30
  unit_square.max.must_equal Point[1,1]
27
31
  end
@@ -111,6 +111,10 @@ describe Geometry::Rectangle do
111
111
  rectangle.center.must_equal Point[2,3]
112
112
  end
113
113
 
114
+ it 'must always be closed' do
115
+ subject.closed?.must_equal true
116
+ end
117
+
114
118
  it "have a width property" do
115
119
  assert_equal(2, rectangle.width)
116
120
  end
@@ -4,7 +4,13 @@ require 'geometry/regular_polygon'
4
4
  describe Geometry::RegularPolygon do
5
5
  RegularPolygon = Geometry::RegularPolygon
6
6
 
7
- describe "when constructed with named center and radius arguments" do
7
+ subject { RegularPolygon.new sides:4, center:[1,2], radius:3 }
8
+
9
+ it 'must always be closed' do
10
+ subject.closed?.must_equal true
11
+ end
12
+
13
+ describe 'when constructed with a center and circumradius' do
8
14
  let(:polygon) { RegularPolygon.new sides:4, center:[1,2], radius:3 }
9
15
  subject { RegularPolygon.new sides:4, center:[1,2], radius:3 }
10
16
 
@@ -33,16 +39,19 @@ describe Geometry::RegularPolygon do
33
39
  subject.vertices.must_equal [Point[4.0, 2.0], Point[1.0000000000000002, 5.0], Point[-2.0, 2.0000000000000004], Point[0.9999999999999994, -1.0]]
34
40
  end
35
41
  end
42
+
43
+ it 'must have an indiameter' do
44
+ subject.indiameter.must_be_close_to 4.242
45
+ end
46
+
47
+ it 'must have an inradius' do
48
+ subject.inradius.must_be_close_to 2.121
49
+ end
36
50
  end
37
51
 
38
52
  describe "when constructed with a center and diameter" do
39
53
  let(:polygon) { RegularPolygon.new sides:4, center:[1,2], diameter:4 }
40
54
 
41
- it "must be a DiameterRegularPolygon" do
42
- polygon.must_be_instance_of(Geometry::DiameterRegularPolygon)
43
- polygon.must_be_kind_of(RegularPolygon)
44
- end
45
-
46
55
  it "must have the correct number of sides" do
47
56
  polygon.edge_count.must_equal 4
48
57
  end
@@ -67,11 +76,6 @@ describe Geometry::RegularPolygon do
67
76
  describe "when constructed with a diameter and no center" do
68
77
  let(:polygon) { RegularPolygon.new sides:4, diameter:4 }
69
78
 
70
- it "must be a DiameterRegularPolygon" do
71
- polygon.must_be_instance_of(Geometry::DiameterRegularPolygon)
72
- polygon.must_be_kind_of(RegularPolygon)
73
- end
74
-
75
79
  it "must have the correct number of sides" do
76
80
  polygon.edge_count.must_equal 4
77
81
  end
@@ -89,6 +93,41 @@ describe Geometry::RegularPolygon do
89
93
  end
90
94
  end
91
95
 
96
+ describe 'when constructed with an indiameter and center' do
97
+ subject { RegularPolygon.new sides:6, indiameter:4 }
98
+
99
+ it 'must have a circumdiameter' do
100
+ subject.diameter.must_be_close_to 4.618
101
+ end
102
+
103
+ it 'must have a circumradius' do
104
+ subject.circumradius.must_be_close_to 2.309
105
+ end
106
+
107
+ it 'must have an indiameter' do
108
+ subject.indiameter.must_be_close_to 4
109
+ end
110
+
111
+ it 'must have an inradius' do
112
+ subject.inradius.must_be_close_to 2
113
+ end
114
+ end
115
+
116
+ describe 'when constructed with an inradius and center' do
117
+ subject { RegularPolygon.new sides:6, inradius:4 }
118
+
119
+ it 'must have a circumradius' do
120
+ subject.circumradius.must_be_close_to 4.618
121
+ end
122
+
123
+ it 'must have points' do
124
+ expected_points = [Point[4.618, 0], Point[2.309, 4], Point[-2.309, 4], Point[-4.618, 0], Point[-2.309, -4], Point[2.309, -4]]
125
+ subject.points.zip(expected_points) do |point0, point1|
126
+ point0.to_a.zip(point1.to_a) {|a, b| a.must_be_close_to b }
127
+ end
128
+ end
129
+ end
130
+
92
131
  describe "properties" do
93
132
  subject { RegularPolygon.new sides:6, diameter:4 }
94
133
 
@@ -101,6 +140,13 @@ describe Geometry::RegularPolygon do
101
140
  end
102
141
  end
103
142
 
143
+ it 'must have points' do
144
+ expected_points = [Point[2, 0], Point[1, 1.732], Point[-1, 1.732], Point[-2, 0], Point[-1, -1.732], Point[1, -1.732]]
145
+ subject.points.zip(expected_points) do |point0, point1|
146
+ point0.to_a.zip(point1.to_a) {|a, b| a.must_be_close_to b }
147
+ end
148
+ end
149
+
104
150
  it "must have a bounds property that returns a Rectangle" do
105
151
  subject.bounds.must_equal Rectangle.new([-2,-2], [2,2])
106
152
  end
@@ -93,6 +93,8 @@ describe Geometry::Rotation do
93
93
  end
94
94
 
95
95
  describe "when transforming a Point" do
96
+ subject { Rotation.new(angle:Math::PI/2) }
97
+
96
98
  describe "when no rotation is set" do
97
99
  it "must return the Point" do
98
100
  Rotation.new.transform(Point[1,0]).must_equal Point[1,0]
@@ -104,5 +106,9 @@ describe Geometry::Rotation do
104
106
  rotated_point.x.must_be_close_to 0
105
107
  rotated_point.y.must_be_close_to 1
106
108
  end
109
+
110
+ it 'must transform a PointZero' do
111
+ subject.transform(Point.zero).must_equal Point.zero
112
+ end
107
113
  end
108
114
  end
@@ -41,12 +41,21 @@ describe Geometry::Size do
41
41
  end
42
42
  end
43
43
 
44
- it "allow indexed element access" do
45
- size = Geometry::Size[5,6]
46
- assert_equal(2, size.size)
47
- assert_equal(5, size[0])
48
- assert_equal(6, size[1])
44
+ describe 'when array access' do
45
+ it 'must allow indexed access' do
46
+ size = Geometry::Size[5,6]
47
+ size.size.must_equal 2
48
+ size[0].must_equal 5
49
+ size[1].must_equal 6
50
+ end
51
+
52
+ it 'must slize with a start index and a length' do
53
+ size = Geometry::Size[5, 6, 7]
54
+ slice = size[1,2]
55
+ slice.length.must_equal 2
56
+ end
49
57
  end
58
+
50
59
  it "allow named element access" do
51
60
  size = Geometry::Size[5,6,7]
52
61
  assert_equal(3, size.size)
@@ -99,9 +108,15 @@ describe Geometry::Size do
99
108
 
100
109
  it 'must inset with horizontal and vertical insets' do
101
110
  subject.inset(4).must_equal Geometry::Size[6, 6]
102
- subject.inset(2,3).must_equal Geometry::Size[8, 7]
103
- subject.inset(x:2, y:3).must_equal Geometry::Size[8, 7]
111
+ subject.inset(2,3).must_equal Geometry::Size[6, 4]
112
+ subject.inset(x:2, y:3).must_equal Geometry::Size[6, 4]
113
+ end
114
+
115
+ it 'must inset with left and top' do
104
116
  subject.inset(left:2, top:3).must_equal Geometry::Size[8, 7]
117
+ end
118
+
119
+ it 'must inset with right and bottom' do
105
120
  subject.inset(right:2, bottom:3).must_equal Geometry::Size[8, 7]
106
121
  end
107
122
 
@@ -111,13 +126,19 @@ describe Geometry::Size do
111
126
 
112
127
  it 'must outset' do
113
128
  subject.outset(4).must_equal Geometry::Size[14, 14]
114
- subject.outset(2,3).must_equal Geometry::Size[12, 13]
115
- subject.outset(x:2, y:3).must_equal Geometry::Size[12, 13]
129
+ subject.outset(2,3).must_equal Geometry::Size[14, 16]
130
+ subject.outset(x:2, y:3).must_equal Geometry::Size[14, 16]
131
+ end
132
+
133
+ it 'must outset with left and top' do
116
134
  subject.outset(left:2, top:3).must_equal Geometry::Size[12, 13]
135
+ end
136
+
137
+ it 'must outset with right and bottom' do
117
138
  subject.outset(right:2, bottom:3).must_equal Geometry::Size[12, 13]
118
139
  end
119
140
 
120
- it 'must inset with insets for top, left, bottom, right' do
141
+ it 'must outset with insets for top, left, bottom, right' do
121
142
  subject.outset(top:1, left:2, bottom:3, right:4).must_equal Geometry::Size[16, 14]
122
143
  end
123
144
  end