geometry 6.4 → 6.5

Sign up to get free protection for your applications and to get access to all the features.
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: []