geometry 6.4 → 6.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 2071223ccd3ab40dc84675595b6b204aa0d7df10
4
- data.tar.gz: ed6b83fe034a5734ca9938c7ab54f4a4fcdda736
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YTE5MmE5YjU5ZDBkOTZiNGY0OGI5NzU5NDU4Yzk1OTk3Y2VjNDBhYw==
5
+ data.tar.gz: !binary |-
6
+ N2QyODkzMTkwYzhkZjhmYjg2MjliOTViYTM4ZjkxN2JkMDA4NDAyOQ==
5
7
  SHA512:
6
- metadata.gz: d78e31275dd418edf77a9067157213b63690bb7139ccf8c8561b228bb51e7be9e8b72e3a9187f02beb8d77ddc95427f882454f49c4827196f832acadec131e3c
7
- data.tar.gz: ba61dfc2b8d83090d59fe4d5348d3b184edeca188bf59c604d6888644a7392b943f8979ac4ea82392b1d8a026b53873128bab58c64702af149c3be68c1852057
8
+ metadata.gz: !binary |-
9
+ ODc3NmE4ZDEzMDg0YjVhNGI0YmU0YjY4NTNkMTM3Mjk4NDFkYjRlMDZiZjkw
10
+ Y2M2ZWNmYTc1NzU2ODFkN2Y2NGI3NTYzYzE2NTcwY2IwMWVlODYzM2U1NmIx
11
+ NzNmYjM3OTEyMDY3NGVhZjU3NTZiNzY1YmQ1ZDVmODEzODE3N2I=
12
+ data.tar.gz: !binary |-
13
+ ZDU2NTJmODQ1ZTAyMzc2NGJiNjFhM2E4NTBhNWIxNjY5M2JjNThhNWJjN2Rm
14
+ MjAwNTYwMjlkMWE1N2UyNTMwZTMxNWZkNDc5NTU3NzhiNDlhOTdjMmY0NzBk
15
+ ZWRiNmVlMDgwZjVjNzY5YjM0ZTMyM2U4M2UzOGU0MzIzYmVkMjM=
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "geometry"
6
- s.version = '6.4'
6
+ s.version = '6.5'
7
7
  s.authors = ["Brandon Fosdick"]
8
8
  s.email = ["bfoz@bfoz.net"]
9
9
  s.homepage = "http://github.com/bfoz/geometry"
@@ -66,6 +66,24 @@ known as a Ring, is a circle that ate another circle.
66
66
  @outer_diameter = options[:outer_diameter] || options[:diameter]
67
67
  @outer_radius = options[:outer_radius] || options[:radius]
68
68
  end
69
+
70
+ # @!attribute max
71
+ # @return [Point] The upper right corner of the bounding {Rectangle}
72
+ def max
73
+ @center+radius
74
+ end
75
+
76
+ # @!attribute min
77
+ # @return [Point] The lower left corner of the bounding {Rectangle}
78
+ def min
79
+ @center-radius
80
+ end
81
+
82
+ # @!attribute minmax
83
+ # @return [Array<Point>] The lower left and upper right corners of the bounding {Rectangle}
84
+ def minmax
85
+ [self.min, self.max]
86
+ end
69
87
  end
70
88
 
71
89
  # Ring is an alias of Annulus because that's the word that most people use,
@@ -31,6 +31,15 @@ Supports two-point, slope-intercept, and point-slope initializer forms
31
31
  class Line
32
32
  include ClusterFactory
33
33
 
34
+ # @!attribute [r] horizontal?
35
+ # @return [Boolean] true if the slope is zero
36
+
37
+ # @!attribute [r] slope
38
+ # @return [Number] the slope of the {Line}
39
+
40
+ # @!attribute [r] vertical?
41
+ # @return [Boolean] true if the slope is infinite
42
+
34
43
  # @overload [](Array, Array)
35
44
  # @return [TwoPointLine]
36
45
  # @overload [](Point, Point)
@@ -85,15 +94,34 @@ Supports two-point, slope-intercept, and point-slope initializer forms
85
94
  end
86
95
  end
87
96
 
97
+ module SlopedLine
98
+ # @!attribute slope
99
+ # @return [Number] the slope of the {Line}
100
+ attr_reader :slope
101
+
102
+ # @!attribute horizontal?
103
+ # @return [Boolean] true if the slope is zero
104
+ def horizontal?
105
+ slope.zero?
106
+ end
107
+
108
+ # @!attribute vertical?
109
+ # @return [Boolean] true if the slope is infinite
110
+ def vertical?
111
+ slope.infinite? != nil
112
+ rescue # Non-Float's don't have an infinite? method
113
+ false
114
+ end
115
+ end
116
+
88
117
  # @private
89
118
  class PointSlopeLine < Line
119
+ include SlopedLine
120
+
90
121
  # @!attribute point
91
122
  # @return [Point] the stating point
92
123
  attr_reader :point
93
124
 
94
- # @return [Number] the slope of the {Line}
95
- attr_reader :slope
96
-
97
125
  # @param point [Point] a {Point} that lies on the {Line}
98
126
  # @param slope [Number] the slope of the {Line}
99
127
  def initialize(point, slope)
@@ -126,12 +154,23 @@ Supports two-point, slope-intercept, and point-slope initializer forms
126
154
  def to_s
127
155
  'Line(' + @slope.to_s + ',' + @point.to_s + ')'
128
156
  end
157
+
158
+ # Find the requested axis intercept
159
+ # @param axis [Symbol] the axis to intercept (either :x or :y)
160
+ # @return [Number] the location of the intercept
161
+ def intercept(axis=:y)
162
+ case axis
163
+ when :x
164
+ vertical? ? point.x : (horizontal? ? nil : (slope * point.x - point.y))
165
+ when :y
166
+ vertical? ? nil : (horizontal? ? point.y : (point.y - slope * point.x))
167
+ end
168
+ end
129
169
  end
130
170
 
131
171
  # @private
132
172
  class SlopeInterceptLine < Line
133
- # @return [Number] the slope of the {Line}
134
- attr_reader :slope
173
+ include SlopedLine
135
174
 
136
175
  # @param slope [Number] the slope
137
176
  # @param intercept [Number] the location of the y-axis intercept
@@ -160,13 +199,9 @@ Supports two-point, slope-intercept, and point-slope initializer forms
160
199
  (intercept == other.intercept) && (slope == other.slope)
161
200
  end
162
201
 
163
- def horizontal?
164
- 0 == @slope
165
- end
166
- def vertical?
167
- (1/0.0) == @slope
168
- end
169
-
202
+ # Find the requested axis intercept
203
+ # @param axis [Symbol] the axis to intercept (either :x or :y)
204
+ # @return [Number] the location of the intercept
170
205
  def intercept(axis=:y)
171
206
  case axis
172
207
  when :x
@@ -183,11 +218,21 @@ Supports two-point, slope-intercept, and point-slope initializer forms
183
218
 
184
219
  # @private
185
220
  class TwoPointLine < Line
186
- attr_reader :first, :last
187
-
188
- def initialize(point0, point1)
189
- @first, @last = [Point[point0], Point[point1]]
221
+ # @!attribute first
222
+ # @return [Point] the {Line}'s starting point
223
+ attr_reader :first
224
+
225
+ # @!attribute last
226
+ # @return [Point] the {Line}'s end point
227
+ attr_reader :last
228
+
229
+ # @param first [Point] the starting point
230
+ # @param last [Point] the end point
231
+ def initialize(first, last)
232
+ @first = Point[first]
233
+ @last = Point[last]
190
234
  end
235
+
191
236
  def inspect
192
237
  'Line(' + @first.inspect + ', ' + @last.inspect + ')'
193
238
  end
@@ -221,6 +266,27 @@ Supports two-point, slope-intercept, and point-slope initializer forms
221
266
  def slope
222
267
  (last.y - first.y)/(last.x - first.x)
223
268
  end
269
+
270
+ def horizontal?
271
+ first.y == last.y
272
+ end
273
+
274
+ def vertical?
275
+ first.x == last.x
276
+ end
277
+
278
+ # Find the requested axis intercept
279
+ # @param axis [Symbol] the axis to intercept (either :x or :y)
280
+ # @return [Number] the location of the intercept
281
+ def intercept(axis=:y)
282
+ case axis
283
+ when :x
284
+ vertical? ? first.x : (horizontal? ? nil : (first.x - first.y/slope))
285
+ when :y
286
+ vertical? ? nil : (horizontal? ? first.y : (first.y - slope * first.x))
287
+ end
288
+ end
289
+
224
290
  # @endgroup
225
291
  end
226
292
  end
@@ -128,7 +128,13 @@ geometry class (x, y, z).
128
128
  @elements.max
129
129
  else
130
130
  args = args.first if 1 == args.size
131
- self.class[@elements.zip(args).map(&:max)]
131
+ case args
132
+ when PointIso then self.class[@elements.map {|e| [e, args.value].max }]
133
+ when PointOne then self.class[@elements.map {|e| [e, 1].max }]
134
+ when PointZero then self.class[@elements.map {|e| [e, 0].max }]
135
+ else
136
+ self.class[@elements.zip(args).map(&:max)]
137
+ end
132
138
  end
133
139
  end
134
140
 
@@ -141,7 +147,13 @@ geometry class (x, y, z).
141
147
  @elements.min
142
148
  else
143
149
  args = args.first if 1 == args.size
144
- self.class[@elements.zip(args).map(&:min)]
150
+ case args
151
+ when PointIso then self.class[@elements.map {|e| [e, args.value].min }]
152
+ when PointOne then self.class[@elements.map {|e| [e, 1].min }]
153
+ when PointZero then self.class[@elements.map {|e| [e, 0].min }]
154
+ else
155
+ self.class[@elements.zip(args).map(&:min)]
156
+ end
145
157
  end
146
158
  end
147
159
 
@@ -157,6 +169,30 @@ geometry class (x, y, z).
157
169
  end
158
170
  end
159
171
 
172
+ # Returns a new {Point} with the given number of elements removed from the end
173
+ # @return [Point] the popped elements
174
+ def pop(count=1)
175
+ self.class[to_a.pop(count)]
176
+ end
177
+
178
+ # Returns a new {Point} with the given elements appended
179
+ # @return [Point]
180
+ def push(*args)
181
+ self.class[to_a.push(*args)]
182
+ end
183
+
184
+ # Removes the first element and returns it
185
+ # @return [Point] the shifted elements
186
+ def shift(count=1)
187
+ self.class[to_a.shift(count)]
188
+ end
189
+
190
+ # Prepend the given objects and return a new {Point}
191
+ # @return [Point]
192
+ def unshift(*args)
193
+ self.class[to_a.unshift(*args)]
194
+ end
195
+
160
196
  # @group Accessors
161
197
  # @param [Integer] i Index into the {Point}'s elements
162
198
  # @return [Numeric] Element i (starting at 0)
@@ -91,6 +91,18 @@ An object repesenting a N-dimensional {Point} with identical elements.
91
91
  end
92
92
  end
93
93
 
94
+ # Returns a new {Point} with the given number of elements removed from the end
95
+ # @return [Point] the popped elements
96
+ def pop(count=1)
97
+ Point[Array.new(count, @value)]
98
+ end
99
+
100
+ # Removes the first element and returns it
101
+ # @return [Point] the shifted elements
102
+ def shift(count=1)
103
+ Point[Array.new(count, @value)]
104
+ end
105
+
94
106
  # @group Accessors
95
107
  # @param i [Integer] Index into the {Point}'s elements
96
108
  # @return [Numeric] Element i (starting at 0)
@@ -67,43 +67,55 @@ everything else, regardless of size. It's similar to the
67
67
  end
68
68
  # @endgroup
69
69
 
70
- # @override max()
71
- # @return [Number] The maximum value of the {Point}'s elements
72
- # @override max(point)
73
- # @return [Point] The element-wise maximum values of the receiver and the given {Point}
74
- def max(*args)
75
- if args.empty?
76
- 1
77
- else
78
- args = args.first if 1 == args.size
79
- Point[Array.new(args.size, 1).zip(args).map(&:max)]
70
+ # @override max()
71
+ # @return [Number] The maximum value of the {Point}'s elements
72
+ # @override max(point)
73
+ # @return [Point] The element-wise maximum values of the receiver and the given {Point}
74
+ def max(*args)
75
+ if args.empty?
76
+ 1
77
+ else
78
+ args = args.first if 1 == args.size
79
+ Point[Array.new(args.size, 1).zip(args).map(&:max)]
80
+ end
80
81
  end
81
- end
82
82
 
83
- # @override min()
84
- # @return [Number] The minimum value of the {Point}'s elements
85
- # @override min(point)
86
- # @return [Point] The element-wise minimum values of the receiver and the given {Point}
87
- def min(*args)
88
- if args.empty?
89
- 1
90
- else
91
- args = args.first if 1 == args.size
92
- Point[Array.new(args.size, 1).zip(args).map(&:min)]
83
+ # @override min()
84
+ # @return [Number] The minimum value of the {Point}'s elements
85
+ # @override min(point)
86
+ # @return [Point] The element-wise minimum values of the receiver and the given {Point}
87
+ def min(*args)
88
+ if args.empty?
89
+ 1
90
+ else
91
+ args = args.first if 1 == args.size
92
+ Point[Array.new(args.size, 1).zip(args).map(&:min)]
93
+ end
93
94
  end
94
- end
95
95
 
96
- # @override minmax()
97
- # @return [Array<Number>] The minimum value of the {Point}'s elements
98
- # @override min(point)
99
- # @return [Array<Point>] The element-wise minimum values of the receiver and the given {Point}
100
- def minmax(*args)
101
- if args.empty?
102
- [1, 1]
103
- else
104
- [min(*args), max(*args)]
96
+ # @override minmax()
97
+ # @return [Array<Number>] The minimum value of the {Point}'s elements
98
+ # @override min(point)
99
+ # @return [Array<Point>] The element-wise minimum values of the receiver and the given {Point}
100
+ def minmax(*args)
101
+ if args.empty?
102
+ [1, 1]
103
+ else
104
+ [min(*args), max(*args)]
105
+ end
106
+ end
107
+
108
+ # Returns a new {Point} with the given number of elements removed from the end
109
+ # @return [Point] the popped elements
110
+ def pop(count=1)
111
+ Point[Array.new(count, 1)]
112
+ end
113
+
114
+ # Removes the first element and returns it
115
+ # @return [Point] the shifted elements
116
+ def shift(count=1)
117
+ Point[Array.new(count, 1)]
105
118
  end
106
- end
107
119
 
108
120
  # @group Arithmetic
109
121
 
@@ -105,6 +105,18 @@ everything else, regardless of size. You can think of it as an application of th
105
105
  end
106
106
  end
107
107
 
108
+ # Returns a new {Point} with the given number of elements removed from the end
109
+ # @return [Point] the popped elements
110
+ def pop(count=1)
111
+ Point[Array.new(count, 0)]
112
+ end
113
+
114
+ # Removes the first element and returns it
115
+ # @return [Point] the shifted elements
116
+ def shift(count=1)
117
+ Point[Array.new(count, 0)]
118
+ end
119
+
108
120
  # @group Arithmetic
109
121
 
110
122
  # @group Unary operators
@@ -180,4 +180,19 @@ system's X-axis:
180
180
  @translation ? (@translation + point) : point
181
181
  end
182
182
  end
183
+
184
+ # @override translation(x, y, z)
185
+ # Construct a new translation from the given values
186
+ # @param x [Number] The distance to translate along the X-axis
187
+ # @param y [Number] The distance to translate along the Y-axis
188
+ # @param z [Number] The distance to translate along the Z-axis
189
+ # @override translation([x, y, z])
190
+ # Construct a new translation from an array of values
191
+ # @override translation(point)
192
+ # Construct a new translation from a {Point}
193
+ # @param point [Point] A {Point}
194
+ def self.translation(*args)
195
+ args = *args if args[0].is_a? Array
196
+ Transformation.new translate:args
197
+ end
183
198
  end
@@ -16,6 +16,18 @@ describe Geometry::Annulus do
16
16
  it 'must have a center' do
17
17
  subject.center.must_equal Point[1,2]
18
18
  end
19
+
20
+ it 'must have a max' do
21
+ subject.max.must_equal Point[11, 12]
22
+ end
23
+
24
+ it 'must have a min' do
25
+ subject.min.must_equal Point[-9, -8]
26
+ end
27
+
28
+ it 'must have a min and a max' do
29
+ subject.minmax.must_equal [subject.min, subject.max]
30
+ end
19
31
  end
20
32
 
21
33
  describe 'when constructed with a center, inner_radius and radius' do
@@ -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
@@ -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
 
@@ -114,7 +115,24 @@ describe Geometry::Point do
114
115
  Point[1,2].dup.must_equal Point[1,2]
115
116
  end
116
117
 
117
- describe 'minmax' do
118
+ it 'must pop' do
119
+ Point[1,2,3,4].pop.must_equal Point[4]
120
+ Point[1,2,3,4].pop(2).must_equal Point[3,4]
121
+ end
122
+
123
+ it 'must push' do
124
+ Point[1,2].push(3,4).must_equal Point[1,2,3,4]
125
+ end
126
+
127
+ it 'must shift' do
128
+ Point[1,2,3,4].shift.must_equal Point[1]
129
+ end
130
+
131
+ it 'must unshift' do
132
+ Point[2,3,4].unshift(1).must_equal Point[1,2,3,4]
133
+ end
134
+
135
+ describe 'minimum' do
118
136
  it 'must have a minimum' do
119
137
  Point[1,2].min.must_equal 1
120
138
  end
@@ -132,6 +150,20 @@ describe Geometry::Point do
132
150
  Point[1,3].min(4,2).must_equal Point[1,2]
133
151
  end
134
152
 
153
+ it 'must minimum with a PointIso' do
154
+ Point[-5,-5,5].min(PointIso.new(-5/2)).must_equal Point[-5,-5,-5/2]
155
+ end
156
+
157
+ it 'must minimum with a PointOne' do
158
+ Point[-5,-5,5].min(Point.one).must_equal Point[-5,-5,1]
159
+ end
160
+
161
+ it 'must minimum with a PointZero' do
162
+ Point[-5,-5,5].min(Point.zero).must_equal Point[-5,-5,0]
163
+ end
164
+ end
165
+
166
+ describe 'maximum' do
135
167
  it 'must have a maximum' do
136
168
  Point[1,2].max.must_equal 2
137
169
  end
@@ -149,6 +181,20 @@ describe Geometry::Point do
149
181
  Point[1,3].max(4,2).must_equal Point[4,3]
150
182
  end
151
183
 
184
+ it 'must maximum with a PointIso' do
185
+ Point[-5,-5,5].max(PointIso.new(-5/2)).must_equal Point[-5/2, -5/2, 5]
186
+ end
187
+
188
+ it 'must maximum with a PointOne' do
189
+ Point[-5,-5,5].max(Point.one).must_equal Point[1, 1, 5]
190
+ end
191
+
192
+ it 'must maximum with a PointZero' do
193
+ Point[-5,-5,5].max(Point.zero).must_equal Point[0, 0, 5]
194
+ end
195
+ end
196
+
197
+ describe 'minmax' do
152
198
  it 'must have a minmax' do
153
199
  Point[1,2].minmax.must_equal [1,2]
154
200
  end
@@ -161,9 +207,21 @@ describe Geometry::Point do
161
207
  Point[1,3].minmax([4,2]).must_equal [Point[1,2], Point[4,3]]
162
208
  end
163
209
 
164
- it 'must maximum with multiple arguments' do
210
+ it 'must minmax with multiple arguments' do
165
211
  Point[1,3].minmax(4,2).must_equal [Point[1,2], Point[4,3]]
166
212
  end
213
+
214
+ it 'must minmax with a PointIso' do
215
+ Point[-5,-5,5].minmax(PointIso.new(-5/2)).must_equal [Point[-5,-5,-5/2], Point[-5/2, -5/2, 5]]
216
+ end
217
+
218
+ it 'must minmax with a PointOne' do
219
+ Point[-5,-5,5].minmax(Point.one).must_equal [Point[-5,-5,1], Point[1, 1, 5]]
220
+ end
221
+
222
+ it 'must minmax with a PointZero' do
223
+ Point[-5,-5,5].minmax(Point.zero).must_equal [Point[-5,-5,0], Point[0, 0, 5]]
224
+ end
167
225
  end
168
226
 
169
227
  describe "arithmetic" do
@@ -5,6 +5,16 @@ describe Geometry::PointIso do
5
5
  let(: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
@@ -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
@@ -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] }
@@ -84,6 +84,20 @@ describe Geometry::Transformation do
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
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geometry
3
3
  version: !ruby/object:Gem::Version
4
- version: '6.4'
4
+ version: '6.5'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandon Fosdick
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-18 00:00:00.000000000 Z
11
+ date: 2015-03-21 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Geometric primitives and algorithms for Ruby
14
14
  email:
@@ -86,44 +86,18 @@ require_paths:
86
86
  - lib
87
87
  required_ruby_version: !ruby/object:Gem::Requirement
88
88
  requirements:
89
- - - '>='
89
+ - - ! '>='
90
90
  - !ruby/object:Gem::Version
91
91
  version: '2.0'
92
92
  required_rubygems_version: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '>='
94
+ - - ! '>='
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  requirements: []
98
98
  rubyforge_project: geometry
99
- rubygems_version: 2.2.2
99
+ rubygems_version: 2.4.5
100
100
  signing_key:
101
101
  specification_version: 4
102
102
  summary: Geometric primitives and algoritms
103
- test_files:
104
- - test/geometry.rb
105
- - test/geometry/annulus.rb
106
- - test/geometry/arc.rb
107
- - test/geometry/bezier.rb
108
- - test/geometry/circle.rb
109
- - test/geometry/edge.rb
110
- - test/geometry/line.rb
111
- - test/geometry/obround.rb
112
- - test/geometry/path.rb
113
- - test/geometry/point.rb
114
- - test/geometry/point_iso.rb
115
- - test/geometry/point_one.rb
116
- - test/geometry/point_zero.rb
117
- - test/geometry/polygon.rb
118
- - test/geometry/polyline.rb
119
- - test/geometry/rectangle.rb
120
- - test/geometry/regular_polygon.rb
121
- - test/geometry/rotation.rb
122
- - test/geometry/size.rb
123
- - test/geometry/size_one.rb
124
- - test/geometry/size_zero.rb
125
- - test/geometry/square.rb
126
- - test/geometry/transformation.rb
127
- - test/geometry/transformation/composition.rb
128
- - test/geometry/triangle.rb
129
- - test/geometry/vector.rb
103
+ test_files: []