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 +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: []
|