geometry 5 → 6

Sign up to get free protection for your applications and to get access to all the features.
@@ -29,7 +29,7 @@ describe Geometry::Path do
29
29
  end
30
30
 
31
31
  it "with Points and Arcs" do
32
- path = Geometry::Path.new [0,0], [1.0,0.0], Geometry::Arc.new([1,1], 1, -90*Math::PI/180, 0), [2.0,1.0], [1,2]
32
+ path = Geometry::Path.new [0,0], [1.0,0.0], Arc.new(center:[1,1], radius:1, start:-90*Math::PI/180, end:0), [2.0,1.0], [1,2]
33
33
  path.elements.size.must_equal 3
34
34
  path.elements[0].must_be_kind_of Geometry::Edge
35
35
  path.elements[1].must_be_kind_of Geometry::Arc
@@ -37,7 +37,7 @@ describe Geometry::Path do
37
37
  end
38
38
 
39
39
  it "with Edges and Arcs" do
40
- path = Geometry::Path.new Edge.new([0,0], [1.0,0.0]), Geometry::Arc.new([1,1], 1, -90*Math::PI/180, 0), Edge.new([2.0,1.0], [1,2])
40
+ path = Geometry::Path.new Edge.new([0,0], [1.0,0.0]), Arc.new(center:[1,1], radius:1, start:-90*Math::PI/180, end:0), Edge.new([2.0,1.0], [1,2])
41
41
  path.elements.size.must_equal 3
42
42
  path.elements[0].must_be_kind_of Geometry::Edge
43
43
  path.elements[1].must_be_kind_of Geometry::Arc
@@ -45,7 +45,7 @@ describe Geometry::Path do
45
45
  end
46
46
 
47
47
  it "with disjoint Edges and Arcs" do
48
- path = Geometry::Path.new Edge.new([0,0], [1,0]), Geometry::Arc.new([2,1], 1, -90*Math::PI/180, 0), Edge.new([3,1], [1,2])
48
+ path = Geometry::Path.new Edge.new([0,0], [1,0]), Arc.new(center:[2,1], radius:1, start:-90*Math::PI/180, end:0), Edge.new([3,1], [1,2])
49
49
  path.elements.size.must_equal 4
50
50
  path.elements[0].must_be_kind_of Geometry::Edge
51
51
  path.elements[1].must_be_kind_of Geometry::Edge
@@ -54,7 +54,7 @@ describe Geometry::Path do
54
54
  end
55
55
 
56
56
  it "with disjoint Arcs" do
57
- path = Geometry::Path.new Geometry::Arc.new([2,1], 1, -90*Math::PI/180, 0), Geometry::Arc.new([3,1], 1, -90*Math::PI/180, 0)
57
+ path = Geometry::Path.new Arc.new(center:[2,1], radius:1, start:-90*Math::PI/180, end:0), Arc.new(center:[3,1], radius:1, start:-90*Math::PI/180, end:0)
58
58
  path.elements.size.must_equal 3
59
59
  path.elements[0].must_be_kind_of Geometry::Arc
60
60
  path.elements[1].must_be_kind_of Geometry::Edge
@@ -62,6 +62,5 @@ describe Geometry::Path do
62
62
 
63
63
  path.elements[0].last.must_equal path.elements[1].first
64
64
  end
65
-
66
65
  end
67
66
  end
@@ -11,6 +11,12 @@ describe Geometry::Point do
11
11
  point.x.must_equal 3
12
12
  point.y.must_equal 4
13
13
  end
14
+
15
+ it "must return the PointZero when constructed from a PointZero" do
16
+ original_point = Geometry::PointZero.new
17
+ point = Geometry::Point[original_point]
18
+ point.must_be_same_as original_point
19
+ end
14
20
  end
15
21
 
16
22
  it "create a Point object using list syntax" do
@@ -102,12 +108,9 @@ describe Geometry::Point do
102
108
  (left + [5,6]).must_equal Point[6,8]
103
109
  end
104
110
 
105
- it "must raise TypeError when adding a scalar to a Point of dimension greater than 1" do
106
- lambda { left + 1 }.must_raise Geometry::DimensionMismatch
107
- end
108
-
109
- it "must support adding a Numeric to a Point with a size of 1" do
110
- (Point[1] + 2).must_equal Point[3]
111
+ it "must add a Numeric to all elements" do
112
+ (left + 2).must_equal Point[3,4]
113
+ (2 + left).must_equal Point[3,4]
111
114
  end
112
115
 
113
116
  it "must raise an exception when adding mismatched sizes" do
@@ -130,12 +133,9 @@ describe Geometry::Point do
130
133
  (left - [5,6]).must_equal Point[-4, -4]
131
134
  end
132
135
 
133
- it "must raise an exception when subtracting a scalar from a Vector" do
134
- lambda { left - 1 }.must_raise Geometry::DimensionMismatch
135
- end
136
-
137
- it "must subtract a Numeric from a Point of size 1" do
138
- (Point[3] - 2).must_equal Point[1]
136
+ it "must subtract a Numeric from all elements" do
137
+ (left - 2).must_equal Point[-1, 0]
138
+ (2 - left).must_equal Point[1,0]
139
139
  end
140
140
 
141
141
  it "must raise an exception when subtracting mismatched sizes" do
@@ -17,7 +17,19 @@ describe Geometry::PointZero do
17
17
  (-zero).must_be :eql?, 0
18
18
  (-zero).must_be_instance_of(Geometry::PointZero)
19
19
  end
20
-
20
+
21
+ describe "Accessors" do
22
+ it "must return 0 for array access" do
23
+ zero[3].must_equal 0
24
+ end
25
+
26
+ it "must return 0 for named element access" do
27
+ zero.x.must_equal 0
28
+ zero.y.must_equal 0
29
+ zero.z.must_equal 0
30
+ end
31
+ end
32
+
21
33
  describe "when adding" do
22
34
  it "must return a number" do
23
35
  (zero + 3).must_equal 3
@@ -29,10 +41,15 @@ describe Geometry::PointZero do
29
41
  (left + zero).must_be_kind_of Point
30
42
  end
31
43
 
32
- it "must return a Point when adding an array" do
44
+ it "must return an Array when adding an array" do
33
45
  (zero + [5,6]).must_equal [5,6]
34
46
  # ([5,6] + zero).must_equal [5,6]
35
47
  end
48
+
49
+ it "must return a Point when adding a Size" do
50
+ (zero + Size[5,6]).must_be_instance_of(Point)
51
+ (zero + Size[5,6]).must_equal Point[5,6]
52
+ end
36
53
  end
37
54
 
38
55
  describe "when subtracting" do
@@ -50,6 +67,11 @@ describe Geometry::PointZero do
50
67
  (zero - [5,6]).must_equal [-5, -6]
51
68
  # ([5,6] - zero).must_equal [5,6]
52
69
  end
70
+
71
+ it "must return a Point when subtracting a Size" do
72
+ (zero - Size[5,6]).must_be_instance_of(Point)
73
+ (zero - Size[5,6]).must_equal Point[-5,-6]
74
+ end
53
75
  end
54
76
 
55
77
  describe "multiplication" do
@@ -104,7 +126,7 @@ describe Geometry::PointZero do
104
126
  end
105
127
 
106
128
  describe "comparison" do
107
- let(:zero) { Geometry::PointZero.new }
129
+ subject { Geometry::PointZero.new }
108
130
 
109
131
  it "must be equal to 0 and 0.0" do
110
132
  zero.must_be :eql?, 0
@@ -119,7 +141,9 @@ describe Geometry::PointZero do
119
141
  it "must be equal to an Array of zeros" do
120
142
  zero.must_be :==, [0,0]
121
143
  zero.must_be :eql?, [0,0]
144
+ zero.must_be :===, [0,0]
122
145
  [0,0].must_equal zero
146
+ subject.must_equal [0,0]
123
147
  end
124
148
 
125
149
  it "must not be equal to a non-zero Array" do
@@ -130,7 +154,9 @@ describe Geometry::PointZero do
130
154
  it "must be equal to a Point at the origin" do
131
155
  zero.must_be :==, Point[0,0]
132
156
  zero.must_be :eql?, Point[0,0]
157
+ zero.must_be :===, Point[0,0]
133
158
  Point[0,0].must_equal zero
159
+ subject.must_equal Point[0,0]
134
160
  end
135
161
 
136
162
  it "must not be equal to a Point not at the origin" do
@@ -2,7 +2,6 @@ require 'minitest/autorun'
2
2
  require 'geometry/polygon'
3
3
 
4
4
  describe Geometry::Polygon do
5
- Point = Geometry::Point
6
5
  Polygon = Geometry::Polygon
7
6
 
8
7
  let(:cw_unit_square) { Polygon.new [0,0], [0,1], [1,1], [1,0] }
@@ -59,6 +58,18 @@ describe Geometry::Polygon do
59
58
  assert_equal(polygon.edges.first.first, polygon.edges.last.last)
60
59
  end
61
60
 
61
+ describe "orientation" do
62
+ it "must return true for clockwise" do
63
+ Polygon.new([0,0], [0,1], [1,1], [1,0]).clockwise?.must_equal true
64
+ Polygon.new([1,1], [1,3], [3,3], [3,1]).clockwise?.must_equal true
65
+ end
66
+
67
+ it "must return fale for counterclockwise" do
68
+ Polygon.new([0,0], [1,0], [1,1], [0,1]).clockwise?.must_equal false
69
+ Polygon.new([1,1], [3,1], [3,3], [1,3]).clockwise?.must_equal false
70
+ end
71
+ end
72
+
62
73
  it "must gift wrap a square polygon" do
63
74
  polygon = Polygon.new [0,0], [1,0], [1,1], [0,1]
64
75
  convex_hull = polygon.wrap
@@ -91,6 +102,18 @@ describe Geometry::Polygon do
91
102
  convex_hull.vertices.must_equal [[0,0], [0,1], [2,1], [2,0], [1,-1]].map {|a| Point[*a]}
92
103
  end
93
104
 
105
+ describe "spaceship" do
106
+ it "with a Point" do
107
+ (unit_square <=> Point[2,0]).must_equal -1
108
+ (unit_square <=> Point[1,0]).must_equal 0
109
+ (unit_square <=> Point[0.5,0.5]).must_equal 1
110
+ end
111
+
112
+ it "with a Point that lies on a horizontal edge" do
113
+ (unit_square <=> Point[0.5,0]).must_equal 0
114
+ end
115
+ end
116
+
94
117
  describe "when outsetting" do
95
118
  it "must outset a unit square" do
96
119
  outset_polygon = unit_square.outset(1)
@@ -129,4 +152,41 @@ describe Geometry::Polygon do
129
152
  polygon.outset(1).must_equal Polygon.new [3, 0], [3, 3], [-2, 3], [-2, -2], [3, -2]
130
153
  end
131
154
  end
155
+
156
+ describe "set operations" do
157
+ describe "union" do
158
+ it "must union two adjacent squares" do
159
+ polygonA = Polygon.new [0,0], [1,0], [1,1], [0,1]
160
+ polygonB = Polygon.new [1,0], [2,0], [2,1], [1,1]
161
+ (polygonA.union polygonB).must_equal Polygon.new [0,0], [2,0], [2,1], [0,1]
162
+ (polygonA + polygonB).must_equal Polygon.new [0,0], [2,0], [2,1], [0,1]
163
+ end
164
+
165
+ it "must union two overlapping squares" do
166
+ polygonA = Polygon.new [0,0], [2,0], [2,2], [0,2]
167
+ polygonB = Polygon.new [1,1], [3,1], [3,3], [1,3]
168
+ expected_polygon = Polygon.new [0,0], [2,0], [2,1], [3,1], [3,3], [1,3], [1,2], [0,2]
169
+ union = polygonA.union polygonB
170
+ union.must_be_kind_of Polygon
171
+ union.must_equal expected_polygon
172
+ end
173
+
174
+ it "must union two overlapping clockwise squares" do
175
+ polygonA = Polygon.new [0,0], [0,2], [2,2], [2,0]
176
+ polygonB = Polygon.new [1,1], [1,3], [3,3], [3,1]
177
+ expected_polygon = Polygon.new [0, 0], [0, 2], [1, 2], [1, 3], [3, 3], [3, 1], [2, 1], [2, 0]
178
+ union = polygonA.union polygonB
179
+ union.must_be_kind_of Polygon
180
+ union.must_equal expected_polygon
181
+ end
182
+
183
+ it "must union two overlapping squares with collinear edges" do
184
+ polygonA = Polygon.new [0,0], [2,0], [2,2], [0,2]
185
+ polygonB = Polygon.new [1,0], [3,0], [3,2], [1,2]
186
+ union = polygonA + polygonB
187
+ union.must_be_kind_of Polygon
188
+ union.must_equal Polygon.new [0,0], [3,0], [3,2], [0,2]
189
+ end
190
+ end
191
+ end
132
192
  end
@@ -2,7 +2,6 @@ require 'minitest/autorun'
2
2
  require 'geometry/polyline'
3
3
 
4
4
  describe Geometry::Polyline do
5
- Point = Geometry::Point
6
5
  Polyline = Geometry::Polyline
7
6
 
8
7
  let(:unit_square) { Polyline.new [0,0], [1,0], [1,1], [0,1] }
@@ -5,54 +5,93 @@ def Rectangle(*args)
5
5
  Geometry::Rectangle.new(*args)
6
6
  end
7
7
 
8
- Point = Geometry::Point
9
- Size = Geometry::Size
10
-
11
8
  describe Geometry::Rectangle do
12
- describe "when constructed" do
13
- it "create a Rectangle object from two Points" do
14
- rectangle = Rectangle [1,2], [3,4]
15
- assert_kind_of(Geometry::Rectangle, rectangle)
9
+ Rectangle = Geometry::Rectangle
10
+
11
+ describe "when initializing" do
12
+ it "must accept two corners as Arrays" do
13
+ rectangle = Rectangle.new [1,2], [2,3]
14
+ rectangle.must_be_kind_of Geometry::Rectangle
15
+ rectangle.height.must_equal 1
16
+ rectangle.width.must_equal 1
17
+ rectangle.origin.must_equal Point[1,2]
16
18
  end
17
19
 
18
- it "create a Rectangle from a width and height" do
19
- rectangle = Rectangle 2, 3
20
- assert_kind_of(Geometry::Rectangle, rectangle)
21
- assert_equal(2, rectangle.width)
22
- assert_equal(3, rectangle.height)
23
- assert_equal(Point[0,0], rectangle.center)
20
+ it "must accept two named corners as Arrays" do
21
+ rectangle = Rectangle.new from:[1,2], to:[2,3]
22
+ rectangle.must_be_kind_of Geometry::Rectangle
23
+ rectangle.height.must_equal 1
24
+ rectangle.width.must_equal 1
25
+ rectangle.origin.must_equal Point[1,2]
24
26
  end
25
27
 
26
- it "create a Rectangle from a Size" do
27
- rectangle = Rectangle Size[2, 3]
28
- assert_kind_of(Geometry::Rectangle, rectangle)
29
- assert_equal(2, rectangle.width)
30
- assert_equal(3, rectangle.height)
31
- assert_equal(Point[0,0], rectangle.center)
28
+ it "must accept named center point and size arguments" do
29
+ rectangle = Rectangle.new center:[1,2], size:[3,4]
30
+ rectangle.must_be_kind_of Geometry::Rectangle
31
+ rectangle.height.must_equal 4
32
+ rectangle.width.must_equal 3
33
+ rectangle.center.must_equal Point[1,2]
32
34
  end
33
35
 
34
- it "create a Rectangle from an origin Point and Size" do
35
- rectangle = Rectangle Point[1,2], Size[2, 3]
36
- assert_kind_of(Geometry::Rectangle, rectangle)
37
- assert_equal(2, rectangle.width)
38
- assert_equal(3, rectangle.height)
39
- assert_equal(Point[1,2], rectangle.origin)
36
+ it "must reject a named center argument with no size argument" do
37
+ -> { Rectangle.new center:[1,2] }.must_raise ArgumentError
40
38
  end
41
39
 
42
- it "create a Rectangle from sides" do
43
- rectangle = Rectangle 1,2,3,4
44
- assert_kind_of(Geometry::Rectangle, rectangle)
45
- assert_equal(2, rectangle.width)
46
- assert_equal(2, rectangle.height)
47
- assert_equal(Point[1,2], rectangle.origin)
40
+ it "must accept named origin point and size arguments" do
41
+ rectangle = Rectangle.new origin:[1,2], size:[3,4]
42
+ rectangle.must_be_kind_of Geometry::Rectangle
43
+ rectangle.height.must_equal 4
44
+ rectangle.width.must_equal 3
45
+ rectangle.origin.must_equal Point[1,2]
46
+ end
47
+
48
+ it "must reject a named origin argument with no size argument" do
49
+ -> { Rectangle.new origin:[1,2] }.must_raise ArgumentError
50
+ end
51
+
52
+ it "must accept a sole named size argument that is an Array" do
53
+ rectangle = Rectangle.new size:[1,2]
54
+ rectangle.must_be_kind_of Geometry::Rectangle
55
+ rectangle.origin.must_equal Point[0,0]
56
+ rectangle.height.must_equal 2
57
+ rectangle.width.must_equal 1
58
+ end
59
+
60
+ it "must accept a sole named size argument that is a Size" do
61
+ rectangle = Rectangle.new size:Size[1,2]
62
+ rectangle.must_be_kind_of Geometry::Rectangle
63
+ rectangle.origin.must_equal Point[0,0]
64
+ rectangle.height.must_equal 2
65
+ rectangle.width.must_equal 1
66
+ end
67
+
68
+ it "must accept named width and height arguments" do
69
+ rectangle = Rectangle.new width:1, height:3
70
+ rectangle.must_be_kind_of Geometry::Rectangle
71
+ rectangle.height.must_equal 3
72
+ rectangle.width.must_equal 1
73
+ end
74
+
75
+ it "must reject width or height by themselves" do
76
+ -> { Rectangle.new height:1 }.must_raise ArgumentError
77
+ -> { Rectangle.new width:1 }.must_raise ArgumentError
78
+ end
79
+
80
+ end
81
+
82
+ describe "comparison" do
83
+ it "must compare equal" do
84
+ rectangle = Rectangle [1,2], [3,4]
85
+ rectangle.must_equal Rectangle([1,2], [3, 4])
48
86
  end
49
87
  end
50
88
 
51
89
  describe "properties" do
90
+ subject { Rectangle.new [1,2], [3,4] }
52
91
  let(:rectangle) { Rectangle [1,2], [3,4] }
53
92
 
54
93
  it "have a center point property" do
55
- assert_equal(rectangle.center, [2,3])
94
+ rectangle.center.must_equal Point[2,3]
56
95
  end
57
96
 
58
97
  it "have a width property" do
@@ -78,5 +117,21 @@ describe Geometry::Rectangle do
78
117
  assert_equal(4, points.size)
79
118
  points.each {|point| assert_kind_of(Geometry::Point, point)}
80
119
  end
120
+
121
+ it "must have a bounds property that returns a Rectangle" do
122
+ subject.bounds.must_equal Rectangle.new([1,2], [3,4])
123
+ end
124
+
125
+ it "must have a minmax property that returns the corners of the bounding rectangle" do
126
+ subject.minmax.must_equal [Point[1,2], Point[3,4]]
127
+ end
128
+
129
+ it "must have a max property that returns the upper right corner of the bounding rectangle" do
130
+ subject.max.must_equal Point[3,4]
131
+ end
132
+
133
+ it "must have a min property that returns the lower left corner of the bounding rectangle" do
134
+ subject.min.must_equal Point[1,2]
135
+ end
81
136
  end
82
137
  end
@@ -0,0 +1,84 @@
1
+ require 'minitest/autorun'
2
+ require 'geometry/regular_polygon'
3
+
4
+ describe Geometry::RegularPolygon do
5
+ RegularPolygon = Geometry::RegularPolygon
6
+
7
+ describe "when constructed with named center and radius arguments" do
8
+ let(:polygon) { RegularPolygon.new sides:4, center:[1,2], radius:3 }
9
+
10
+ it "must create a RegularPolygon" do
11
+ polygon.must_be_instance_of(RegularPolygon)
12
+ end
13
+
14
+ it "must have the correct number of sides" do
15
+ polygon.edge_count.must_equal 4
16
+ end
17
+
18
+ it "must have a center point accessor" do
19
+ polygon.center.must_equal Point[1,2]
20
+ end
21
+
22
+ it "must have a radius accessor" do
23
+ polygon.radius.must_equal 3
24
+ end
25
+
26
+ it "must compare equal" do
27
+ polygon.must_equal RegularPolygon.new(sides:4, center:[1,2], radius:3)
28
+ end
29
+ end
30
+
31
+ describe "when constructed with a center and diameter" do
32
+ let(:polygon) { RegularPolygon.new sides:4, center:[1,2], diameter:4 }
33
+
34
+ it "must be a DiameterRegularPolygon" do
35
+ polygon.must_be_instance_of(Geometry::DiameterRegularPolygon)
36
+ polygon.must_be_kind_of(RegularPolygon)
37
+ end
38
+
39
+ it "must have the correct number of sides" do
40
+ polygon.edge_count.must_equal 4
41
+ end
42
+
43
+ it "must have a center" do
44
+ polygon.center.must_equal Point[1,2]
45
+ end
46
+
47
+ it "must have a diameter" do
48
+ polygon.diameter.must_equal 4
49
+ end
50
+
51
+ it "must calculate the correct radius" do
52
+ polygon.radius.must_equal 2
53
+ end
54
+
55
+ it "must compare equal" do
56
+ polygon.must_equal RegularPolygon.new(sides:4, center:[1,2], diameter:4)
57
+ end
58
+ end
59
+
60
+ describe "when constructed with a diameter and no center" do
61
+ let(:polygon) { RegularPolygon.new sides:4, diameter:4 }
62
+
63
+ it "must be a DiameterRegularPolygon" do
64
+ polygon.must_be_instance_of(Geometry::DiameterRegularPolygon)
65
+ polygon.must_be_kind_of(RegularPolygon)
66
+ end
67
+
68
+ it "must have the correct number of sides" do
69
+ polygon.edge_count.must_equal 4
70
+ end
71
+
72
+ it "must have a nil center" do
73
+ polygon.center.must_be_nil
74
+ end
75
+
76
+ it "must have a diameter" do
77
+ polygon.diameter.must_equal 4
78
+ end
79
+
80
+ it "must calculate the correct radius" do
81
+ polygon.radius.must_equal 2
82
+ end
83
+ end
84
+ end