geometry 6.4 → 6.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +13 -5
- data/geometry.gemspec +1 -1
- data/lib/geometry/annulus.rb +18 -0
- data/lib/geometry/line.rb +82 -16
- data/lib/geometry/point.rb +38 -2
- data/lib/geometry/point_iso.rb +12 -0
- data/lib/geometry/point_one.rb +44 -32
- data/lib/geometry/point_zero.rb +12 -0
- data/lib/geometry/transformation.rb +15 -0
- data/test/geometry/annulus.rb +12 -0
- data/test/geometry/line.rb +73 -0
- data/test/geometry/point.rb +60 -2
- data/test/geometry/point_iso.rb +10 -0
- data/test/geometry/point_one.rb +10 -0
- data/test/geometry/point_zero.rb +45 -35
- data/test/geometry/transformation.rb +14 -0
- metadata +6 -32
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
YTE5MmE5YjU5ZDBkOTZiNGY0OGI5NzU5NDU4Yzk1OTk3Y2VjNDBhYw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
N2QyODkzMTkwYzhkZjhmYjg2MjliOTViYTM4ZjkxN2JkMDA4NDAyOQ==
|
5
7
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ODc3NmE4ZDEzMDg0YjVhNGI0YmU0YjY4NTNkMTM3Mjk4NDFkYjRlMDZiZjkw
|
10
|
+
Y2M2ZWNmYTc1NzU2ODFkN2Y2NGI3NTYzYzE2NTcwY2IwMWVlODYzM2U1NmIx
|
11
|
+
NzNmYjM3OTEyMDY3NGVhZjU3NTZiNzY1YmQ1ZDVmODEzODE3N2I=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZDU2NTJmODQ1ZTAyMzc2NGJiNjFhM2E4NTBhNWIxNjY5M2JjNThhNWJjN2Rm
|
14
|
+
MjAwNTYwMjlkMWE1N2UyNTMwZTMxNWZkNDc5NTU3NzhiNDlhOTdjMmY0NzBk
|
15
|
+
ZWRiNmVlMDgwZjVjNzY5YjM0ZTMyM2U4M2UzOGU0MzIzYmVkMjM=
|
data/geometry.gemspec
CHANGED
data/lib/geometry/annulus.rb
CHANGED
@@ -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,
|
data/lib/geometry/line.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
164
|
-
|
165
|
-
|
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
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
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
|
data/lib/geometry/point.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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)
|
data/lib/geometry/point_iso.rb
CHANGED
@@ -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)
|
data/lib/geometry/point_one.rb
CHANGED
@@ -67,43 +67,55 @@ everything else, regardless of size. It's similar to the
|
|
67
67
|
end
|
68
68
|
# @endgroup
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
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
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
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
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
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
|
|
data/lib/geometry/point_zero.rb
CHANGED
@@ -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
|
data/test/geometry/annulus.rb
CHANGED
@@ -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
|
data/test/geometry/line.rb
CHANGED
@@ -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
|
data/test/geometry/point.rb
CHANGED
@@ -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
|
-
|
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
|
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
|
data/test/geometry/point_iso.rb
CHANGED
@@ -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
|
data/test/geometry/point_one.rb
CHANGED
@@ -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
|
data/test/geometry/point_zero.rb
CHANGED
@@ -5,55 +5,65 @@ describe Geometry::PointZero do
|
|
5
5
|
subject { Geometry::PointZero.new }
|
6
6
|
let(:zero) { Geometry::PointZero.new }
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
subject.
|
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
|
14
|
-
subject.
|
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
|
-
|
18
|
-
|
19
|
-
|
18
|
+
describe 'minmax' do
|
19
|
+
it 'must have a minimum' do
|
20
|
+
subject.min.must_equal 0
|
21
|
+
end
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
-
|
23
|
+
it 'must minimum with another Point' do
|
24
|
+
subject.min(Point[-1,7]).must_equal Point[-1,0]
|
25
|
+
end
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
-
|
27
|
+
it 'must minimum with an Array' do
|
28
|
+
subject.min([-1,7]).must_equal Point[-1,0]
|
29
|
+
end
|
28
30
|
|
29
|
-
|
30
|
-
|
31
|
-
|
31
|
+
it 'must minimum with a multiple arguments' do
|
32
|
+
subject.min(-1,7).must_equal Point[-1,0]
|
33
|
+
end
|
32
34
|
|
33
|
-
|
34
|
-
|
35
|
-
|
35
|
+
it 'must have a maximum' do
|
36
|
+
subject.max.must_equal 0
|
37
|
+
end
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
39
|
+
it 'must maximum with another Point' do
|
40
|
+
subject.max(Point[7,-1]).must_equal Point[7,0]
|
41
|
+
end
|
40
42
|
|
41
|
-
|
42
|
-
|
43
|
-
|
43
|
+
it 'must maximum with an Array' do
|
44
|
+
subject.max([7,-1]).must_equal Point[7,0]
|
45
|
+
end
|
44
46
|
|
45
|
-
|
46
|
-
|
47
|
-
|
47
|
+
it 'must maximum with multiple arguments' do
|
48
|
+
subject.max(7,-1).must_equal Point[7,0]
|
49
|
+
end
|
48
50
|
|
49
|
-
|
50
|
-
|
51
|
-
|
51
|
+
it 'must have a minmax' do
|
52
|
+
subject.minmax.must_equal [0, 0]
|
53
|
+
end
|
52
54
|
|
53
|
-
|
54
|
-
|
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
|
+
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:
|
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.
|
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: []
|