geometry 6 → 6.1
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 +7 -0
- data/README.markdown +6 -1
- data/Rakefile +0 -1
- data/geometry.gemspec +1 -1
- data/lib/geometry/line.rb +14 -3
- data/lib/geometry/point.rb +13 -7
- data/lib/geometry/point_zero.rb +5 -4
- data/lib/geometry/polygon.rb +33 -27
- data/lib/geometry/polyline.rb +129 -23
- data/lib/geometry/rectangle.rb +35 -0
- data/lib/geometry/regular_polygon.rb +35 -3
- data/lib/geometry/rotation.rb +115 -3
- data/lib/geometry/size_zero.rb +2 -1
- data/lib/geometry/transformation.rb +72 -19
- data/lib/geometry/transformation/composition.rb +39 -0
- data/test/geometry/edge.rb +14 -7
- data/test/geometry/line.rb +24 -0
- data/test/geometry/point.rb +55 -14
- data/test/geometry/polygon.rb +28 -6
- data/test/geometry/polyline.rb +176 -0
- data/test/geometry/rectangle.rb +18 -1
- data/test/geometry/regular_polygon.rb +38 -2
- data/test/geometry/rotation.rb +60 -0
- data/test/geometry/transformation.rb +76 -10
- data/test/geometry/transformation/composition.rb +49 -0
- metadata +10 -15
data/test/geometry/rectangle.rb
CHANGED
@@ -76,7 +76,6 @@ describe Geometry::Rectangle do
|
|
76
76
|
-> { Rectangle.new height:1 }.must_raise ArgumentError
|
77
77
|
-> { Rectangle.new width:1 }.must_raise ArgumentError
|
78
78
|
end
|
79
|
-
|
80
79
|
end
|
81
80
|
|
82
81
|
describe "comparison" do
|
@@ -86,6 +85,24 @@ describe Geometry::Rectangle do
|
|
86
85
|
end
|
87
86
|
end
|
88
87
|
|
88
|
+
describe "inset" do
|
89
|
+
subject { Rectangle.new [0,0], [10,10] }
|
90
|
+
|
91
|
+
it "must inset equally" do
|
92
|
+
subject.inset(1).must_equal Rectangle.new [1,1], [9,9]
|
93
|
+
end
|
94
|
+
|
95
|
+
it "must inset vertically and horizontally" do
|
96
|
+
subject.inset(1,2).must_equal Rectangle.new [1,2], [9,8]
|
97
|
+
subject.inset(x:1, y:2).must_equal Rectangle.new [1,2], [9,8]
|
98
|
+
end
|
99
|
+
|
100
|
+
it "must inset from individual sides" do
|
101
|
+
subject.inset(1,2,3,4).must_equal Rectangle.new [2,3], [6,9]
|
102
|
+
subject.inset(top:1, left:2, bottom:3, right:4).must_equal Rectangle.new [2,3], [6,9]
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
89
106
|
describe "properties" do
|
90
107
|
subject { Rectangle.new [1,2], [3,4] }
|
91
108
|
let(:rectangle) { Rectangle [1,2], [3,4] }
|
@@ -6,6 +6,7 @@ describe Geometry::RegularPolygon do
|
|
6
6
|
|
7
7
|
describe "when constructed with named center and radius arguments" do
|
8
8
|
let(:polygon) { RegularPolygon.new sides:4, center:[1,2], radius:3 }
|
9
|
+
subject { RegularPolygon.new sides:4, center:[1,2], radius:3 }
|
9
10
|
|
10
11
|
it "must create a RegularPolygon" do
|
11
12
|
polygon.must_be_instance_of(RegularPolygon)
|
@@ -26,6 +27,12 @@ describe Geometry::RegularPolygon do
|
|
26
27
|
it "must compare equal" do
|
27
28
|
polygon.must_equal RegularPolygon.new(sides:4, center:[1,2], radius:3)
|
28
29
|
end
|
30
|
+
|
31
|
+
describe "properties" do
|
32
|
+
it "must have vertices" do
|
33
|
+
subject.vertices.must_equal [Point[4.0, 2.0], Point[1.0000000000000002, 5.0], Point[-2.0, 2.0000000000000004], Point[0.9999999999999994, -1.0]]
|
34
|
+
end
|
35
|
+
end
|
29
36
|
end
|
30
37
|
|
31
38
|
describe "when constructed with a center and diameter" do
|
@@ -69,8 +76,8 @@ describe Geometry::RegularPolygon do
|
|
69
76
|
polygon.edge_count.must_equal 4
|
70
77
|
end
|
71
78
|
|
72
|
-
it "must
|
73
|
-
polygon.center.
|
79
|
+
it "must be at the origin" do
|
80
|
+
polygon.center.must_equal Point.zero
|
74
81
|
end
|
75
82
|
|
76
83
|
it "must have a diameter" do
|
@@ -81,4 +88,33 @@ describe Geometry::RegularPolygon do
|
|
81
88
|
polygon.radius.must_equal 2
|
82
89
|
end
|
83
90
|
end
|
91
|
+
|
92
|
+
describe "properties" do
|
93
|
+
subject { RegularPolygon.new sides:6, diameter:4 }
|
94
|
+
|
95
|
+
it "must have edges" do
|
96
|
+
expected_edges = [Edge(Point[2, 0], Point[1, 1.732]), Edge(Point[1, 1.732], Point[-1, 1.732]), Edge(Point[-1, 1.732], Point[-2, 0]), Edge(Point[-2, 0], Point[-1, -1.732]), Edge(Point[-1, -1.732], Point[1, -1.732]), Edge(Point[1, -1.732], Point[2, 0])]
|
97
|
+
subject.edges.zip(expected_edges) do |edge1, edge2|
|
98
|
+
edge1.to_a.zip(edge2.to_a) do |point1, point2|
|
99
|
+
point1.to_a.zip(point2.to_a) {|a, b| a.must_be_close_to b }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
it "must have a bounds property that returns a Rectangle" do
|
105
|
+
subject.bounds.must_equal Rectangle.new([-2,-2], [2,2])
|
106
|
+
end
|
107
|
+
|
108
|
+
it "must have a minmax property that returns the corners of the bounding rectangle" do
|
109
|
+
subject.minmax.must_equal [Point[-2,-2], Point[2,2]]
|
110
|
+
end
|
111
|
+
|
112
|
+
it "must have a max property that returns the upper right corner of the bounding rectangle" do
|
113
|
+
subject.max.must_equal Point[2,2]
|
114
|
+
end
|
115
|
+
|
116
|
+
it "must have a min property that returns the lower left corner of the bounding rectangle" do
|
117
|
+
subject.min.must_equal Point[-2,-2]
|
118
|
+
end
|
119
|
+
end
|
84
120
|
end
|
data/test/geometry/rotation.rb
CHANGED
@@ -2,7 +2,29 @@ require 'minitest/autorun'
|
|
2
2
|
require 'geometry/rotation'
|
3
3
|
|
4
4
|
describe Geometry::Rotation do
|
5
|
+
Point = Geometry::Point
|
5
6
|
Rotation = Geometry::Rotation
|
7
|
+
RotationAngle = Geometry::RotationAngle
|
8
|
+
|
9
|
+
describe "when constructed" do
|
10
|
+
it "must accept a rotation angle" do
|
11
|
+
rotation = Rotation.new angle:Math::PI/2
|
12
|
+
rotation.must_be_instance_of(RotationAngle)
|
13
|
+
rotation.angle.must_equal Math::PI/2
|
14
|
+
rotation.x.x.must_be_close_to 0
|
15
|
+
rotation.x.y.must_be_close_to 1
|
16
|
+
rotation.y.x.must_be_close_to -1
|
17
|
+
rotation.y.y.must_be_close_to 0
|
18
|
+
end
|
19
|
+
|
20
|
+
it "must accept an X axis" do
|
21
|
+
rotation = Rotation.new x:[1,0]
|
22
|
+
rotation.must_be_instance_of(RotationAngle)
|
23
|
+
rotation.angle.must_equal 0
|
24
|
+
rotation.x.must_equal Point[1,0]
|
25
|
+
rotation.y.must_equal Point[0,1]
|
26
|
+
end
|
27
|
+
end
|
6
28
|
|
7
29
|
it "must accept x and y axes" do
|
8
30
|
rotation = Geometry::Rotation.new :x => [1,2,3], :y => [4,5,6]
|
@@ -45,4 +67,42 @@ describe Geometry::Rotation do
|
|
45
67
|
Rotation.new(x:[1,2,3], y:[4,5,6]).must_equal Rotation.new(x:[1,2,3], y:[4,5,6])
|
46
68
|
end
|
47
69
|
end
|
70
|
+
|
71
|
+
describe "comparison" do
|
72
|
+
it "must equate equal angles" do
|
73
|
+
Rotation.new(angle:45).must_equal Rotation.new(angle:45)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "must not equate unequal angles" do
|
77
|
+
Rotation.new(angle:10).wont_equal Rotation.new(angle:45)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "composition" do
|
82
|
+
it "must add angles" do
|
83
|
+
(Rotation.new(angle:45) + Rotation.new(angle:45)).must_equal Rotation.new(angle:90)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "must subtract angles" do
|
87
|
+
(Rotation.new(angle:45) - Rotation.new(angle:45)).must_equal Rotation.new(angle:0)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "must negate angles" do
|
91
|
+
(-Rotation.new(angle:45)).must_equal Rotation.new(angle:-45)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "when transforming a Point" do
|
96
|
+
describe "when no rotation is set" do
|
97
|
+
it "must return the Point" do
|
98
|
+
Rotation.new.transform(Point[1,0]).must_equal Point[1,0]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it "must rotate" do
|
103
|
+
rotated_point = Rotation.new(angle:Math::PI/2).transform(Point[1,0])
|
104
|
+
rotated_point.x.must_be_close_to 0
|
105
|
+
rotated_point.y.must_be_close_to 1
|
106
|
+
end
|
107
|
+
end
|
48
108
|
end
|
@@ -58,46 +58,112 @@ describe Geometry::Transformation do
|
|
58
58
|
end
|
59
59
|
|
60
60
|
describe "rotation" do
|
61
|
-
it "must accept an x axis option" do
|
62
|
-
t = Transformation.new :x => [0,1]
|
63
|
-
t.rotation.x.must_equal [0,1]
|
64
|
-
t.identity?.wont_equal true
|
65
|
-
end
|
66
|
-
|
67
61
|
it "must accept a y axis option" do
|
68
62
|
t = Transformation.new :y => [1,0]
|
69
63
|
t.rotation.y.must_equal [1,0]
|
70
64
|
t.identity?.wont_equal true
|
71
65
|
end
|
66
|
+
|
67
|
+
it "must accept a rotation angle" do
|
68
|
+
transformation = Transformation.new angle:90
|
69
|
+
transformation.identity?.wont_equal true
|
70
|
+
transformation.rotation.wont_be_nil
|
71
|
+
transformation.rotation.angle.must_equal 90
|
72
|
+
end
|
73
|
+
|
74
|
+
it "must accept a rotation angle specified by an X-axis" do
|
75
|
+
transformation = Transformation.new x:[0,1]
|
76
|
+
rotation = transformation.rotation
|
77
|
+
rotation.must_be_instance_of(RotationAngle)
|
78
|
+
rotation.angle.must_equal Math::PI/2
|
79
|
+
rotation.x.x.must_be_close_to 0
|
80
|
+
rotation.x.y.must_be_close_to 1
|
81
|
+
rotation.y.x.must_be_close_to -1
|
82
|
+
rotation.y.y.must_be_close_to 0
|
83
|
+
end
|
72
84
|
end
|
73
85
|
end
|
74
86
|
|
75
87
|
describe "comparison" do
|
88
|
+
subject { Transformation.new(origin:[1,2]) }
|
89
|
+
|
76
90
|
it "must equate equal transformations" do
|
77
|
-
|
91
|
+
subject.must_equal Transformation.new(origin:[1,2])
|
92
|
+
end
|
93
|
+
|
94
|
+
it "must not equal nil" do
|
95
|
+
subject.eql?(nil).wont_equal true
|
96
|
+
end
|
97
|
+
|
98
|
+
it "must not equate a translation with a rotation" do
|
99
|
+
subject.wont_equal Transformation.new(x:[0,1,0], y:[1,0,0])
|
100
|
+
end
|
101
|
+
|
102
|
+
it "must equate empty transformations" do
|
103
|
+
Transformation.new.must_equal Transformation.new
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "attributes" do
|
108
|
+
describe "has_rotation?" do
|
109
|
+
it "must properly be true" do
|
110
|
+
Transformation.new(angle:90).has_rotation?.must_equal true
|
111
|
+
end
|
112
|
+
|
113
|
+
it "must properly be false" do
|
114
|
+
Transformation.new.has_rotation?.must_equal false
|
115
|
+
end
|
78
116
|
end
|
79
117
|
end
|
80
118
|
|
81
119
|
describe "composition" do
|
120
|
+
let(:translate_left) { Geometry::Transformation.new origin:[-2,-2] }
|
121
|
+
let(:translate_right) { Geometry::Transformation.new origin:[1,1] }
|
82
122
|
let(:transformation) { Geometry::Transformation.new }
|
83
123
|
|
124
|
+
it "must add pure translation" do
|
125
|
+
(translate_left + translate_right).must_equal Geometry::Transformation.new origin:[-1,-1]
|
126
|
+
end
|
127
|
+
|
128
|
+
it "must add translation and no translation" do
|
129
|
+
(transformation + translate_left).must_equal translate_left
|
130
|
+
(translate_left + transformation).must_equal translate_left
|
131
|
+
end
|
132
|
+
|
84
133
|
it "array addition" do
|
85
134
|
(transformation + [1,2]).translation.must_equal Point[1,2]
|
86
135
|
((transformation + [1,2]) + [2,3]).translation.must_equal Point[3,5]
|
87
|
-
(transformation + [1,2]).rotation.
|
136
|
+
(transformation + [1,2]).rotation.must_be_nil
|
88
137
|
end
|
89
138
|
|
90
139
|
it "must update the translation when an array is subtracted" do
|
91
140
|
(transformation - [1,2]).translation.must_equal Point[-1,-2]
|
92
141
|
((transformation - [1,2]) - [2,3]).translation.must_equal Point[-3,-5]
|
93
|
-
(transformation - [1,2,3]).rotation.
|
142
|
+
(transformation - [1,2,3]).rotation.must_be_nil
|
143
|
+
end
|
144
|
+
|
145
|
+
it "must subtract translation and no translation" do
|
146
|
+
(transformation - translate_left).must_equal translate_left
|
147
|
+
(translate_left - transformation).must_equal translate_left
|
94
148
|
end
|
95
149
|
end
|
96
150
|
|
97
151
|
describe "when transforming a Point" do
|
152
|
+
describe "when no transformation is set" do
|
153
|
+
it "must return the Point" do
|
154
|
+
Transformation.new.transform(Point[1,2]).must_equal Point[1,2];
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
98
158
|
it "must translate" do
|
99
159
|
Geometry::Transformation.new(origin:[0,1]).transform([1,0]).must_equal Point[1,1]
|
100
160
|
end
|
101
|
-
end
|
102
161
|
|
162
|
+
it "must rotate" do
|
163
|
+
rotated_point = Transformation.new(angle:Math::PI/2).transform([1,0])
|
164
|
+
rotated_point.x.must_be_close_to 0
|
165
|
+
rotated_point.y.must_be_close_to 1
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
103
169
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'geometry/transformation/composition'
|
3
|
+
|
4
|
+
describe Geometry::Transformation::Composition do
|
5
|
+
Composition = Geometry::Transformation::Composition
|
6
|
+
Transformation = Geometry::Transformation
|
7
|
+
|
8
|
+
subject { Composition.new }
|
9
|
+
|
10
|
+
describe "when constructed" do
|
11
|
+
it "must accept multiple transformations" do
|
12
|
+
composition = Composition.new(Transformation.new, Transformation.new)
|
13
|
+
composition.size.must_equal 2
|
14
|
+
end
|
15
|
+
|
16
|
+
it "must reject anything that isn't a Transformation" do
|
17
|
+
-> { Composition.new :foo }.must_raise TypeError
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "attributes" do
|
22
|
+
describe "has_rotation?" do
|
23
|
+
it "must properly be true" do
|
24
|
+
Composition.new(Transformation.new angle:90).has_rotation?.must_equal true
|
25
|
+
end
|
26
|
+
|
27
|
+
it "must properly be false" do
|
28
|
+
subject.has_rotation?.must_equal false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "when composing" do
|
34
|
+
it "must append a Transformation" do
|
35
|
+
(Composition.new(Transformation.new) + Transformation.new).size.must_equal 2
|
36
|
+
end
|
37
|
+
|
38
|
+
it "must merge with a Composition" do
|
39
|
+
(Composition.new(Transformation.new) + Composition.new(Transformation.new)).size.must_equal 2
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "when transforming a Point" do
|
44
|
+
it "must handle composed translations" do
|
45
|
+
composition = Composition.new(Transformation.new origin:[1,2]) + Composition.new(Transformation.new [3,4])
|
46
|
+
composition.transform(Point[5,6]).must_equal Point[9, 12]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: geometry
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '6'
|
5
|
-
prerelease:
|
4
|
+
version: '6.1'
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Brandon Fosdick
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-01-13 00:00:00.000000000 Z
|
13
12
|
dependencies: []
|
14
13
|
description: Geometric primitives and algorithms for Ruby
|
15
14
|
email:
|
@@ -43,6 +42,7 @@ files:
|
|
43
42
|
- lib/geometry/size_zero.rb
|
44
43
|
- lib/geometry/square.rb
|
45
44
|
- lib/geometry/transformation.rb
|
45
|
+
- lib/geometry/transformation/composition.rb
|
46
46
|
- lib/geometry/triangle.rb
|
47
47
|
- lib/geometry/vector.rb
|
48
48
|
- test/geometry.rb
|
@@ -63,37 +63,31 @@ files:
|
|
63
63
|
- test/geometry/size_zero.rb
|
64
64
|
- test/geometry/square.rb
|
65
65
|
- test/geometry/transformation.rb
|
66
|
+
- test/geometry/transformation/composition.rb
|
66
67
|
- test/geometry/triangle.rb
|
67
68
|
- test/geometry/vector.rb
|
68
69
|
homepage: http://github.com/bfoz/geometry
|
69
70
|
licenses: []
|
71
|
+
metadata: {}
|
70
72
|
post_install_message:
|
71
73
|
rdoc_options: []
|
72
74
|
require_paths:
|
73
75
|
- lib
|
74
76
|
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
-
none: false
|
76
77
|
requirements:
|
77
|
-
- -
|
78
|
+
- - '>='
|
78
79
|
- !ruby/object:Gem::Version
|
79
80
|
version: '0'
|
80
|
-
segments:
|
81
|
-
- 0
|
82
|
-
hash: -1868771796100540308
|
83
81
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
-
none: false
|
85
82
|
requirements:
|
86
|
-
- -
|
83
|
+
- - '>='
|
87
84
|
- !ruby/object:Gem::Version
|
88
85
|
version: '0'
|
89
|
-
segments:
|
90
|
-
- 0
|
91
|
-
hash: -1868771796100540308
|
92
86
|
requirements: []
|
93
87
|
rubyforge_project: geometry
|
94
|
-
rubygems_version: 1.
|
88
|
+
rubygems_version: 2.1.11
|
95
89
|
signing_key:
|
96
|
-
specification_version:
|
90
|
+
specification_version: 4
|
97
91
|
summary: Geometric primitives and algoritms
|
98
92
|
test_files:
|
99
93
|
- test/geometry.rb
|
@@ -114,5 +108,6 @@ test_files:
|
|
114
108
|
- test/geometry/size_zero.rb
|
115
109
|
- test/geometry/square.rb
|
116
110
|
- test/geometry/transformation.rb
|
111
|
+
- test/geometry/transformation/composition.rb
|
117
112
|
- test/geometry/triangle.rb
|
118
113
|
- test/geometry/vector.rb
|