easy_geometry 0.1.0

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.
@@ -0,0 +1,71 @@
1
+ module EasyGeometry
2
+ module D2
3
+ # A vector in a 2-dimensional Euclidean space.
4
+ class Vector
5
+ attr_reader :x, :y
6
+
7
+ EQUITY_TOLERANCE = 0.0000000000001
8
+
9
+ def initialize(x, y)
10
+ @x = x; @y = y
11
+
12
+ validate!
13
+ converting_to_rational!
14
+ end
15
+
16
+ # Compare self and other Vector.
17
+ def ==(other)
18
+ return false unless other.is_a?(Vector)
19
+ (x - other.x).abs < EQUITY_TOLERANCE && (y - other.y).abs < EQUITY_TOLERANCE
20
+ end
21
+
22
+ # Subtract two vectors.
23
+ def -(other)
24
+ raise TypeError, "Subtract between Vector and #{ other.class } is not defined" unless other.is_a?(Vector)
25
+ Vector.new(self.x - other.x, self.y - other.y)
26
+ end
27
+
28
+ # Returns a non-zero vector that is orthogonal to the
29
+ # line containing `self` and the origin.
30
+ def orthogonal_direction
31
+ # if a coordinate is zero, we can put a 1 there and zeros elsewhere
32
+ return Vector.new(1, 0) if x.zero?
33
+ return Vector.new(0, 1) if y.zero?
34
+
35
+ # if the first two coordinates aren't zero, we can create a non-zero
36
+ # orthogonal vector by swapping them, negating one, and padding with zeros
37
+ Vector.new(-y, x)
38
+ end
39
+
40
+ # It is positive if other vector should be turned counter-clockwise in order to superpose them.
41
+ # It is negetive if other vector should be turned clockwise in order to superpose them.
42
+ # It is zero when vectors are collinear.
43
+ def cross_product(other)
44
+ raise TypeError, "Cross product between Vector and #{ other.class } is not defined" unless other.is_a?(Vector)
45
+ x * other.y - y * other.x
46
+ end
47
+
48
+ # Dot product, also known as inner product or scalar product.
49
+ def dot(other)
50
+ raise TypeError, "Scalar (dot) product between Vector and #{ other.class } is not defined" unless other.is_a?(Vector)
51
+ x * other.x + y * other.y
52
+ end
53
+
54
+ # Converts the vector to a point
55
+ def to_point
56
+ Point.new(x, y)
57
+ end
58
+
59
+ private
60
+
61
+ def validate!
62
+ raise TypeError, 'Coords should be numbers' if !x.is_a?(Numeric) || !y.is_a?(Numeric)
63
+ end
64
+
65
+ def converting_to_rational!
66
+ @x = Rational(x.to_s) unless x.is_a?(Rational)
67
+ @y = Rational(y.to_s) unless y.is_a?(Rational)
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,339 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe EasyGeometry::D2::Line do
4
+ let(:p1) { EasyGeometry::D2::Point.new(0, 0) }
5
+ let(:p2) { EasyGeometry::D2::Point.new(1, 1) }
6
+ let(:l1) { described_class.new([0, 0], [1, 1]) }
7
+ let(:l2) { described_class.new([0, 0], [-1, 1]) }
8
+ let(:l3) { described_class.new([0, 0], [1, 0]) }
9
+ let(:s1) { EasyGeometry::D2::Segment.new([0, 0], [1, 1]) }
10
+ let(:s2) { EasyGeometry::D2::Segment.new([0, 0], [-1, 1]) }
11
+ let(:s3) { EasyGeometry::D2::Segment.new([0, 0], [1, 0]) }
12
+ let(:r1) { EasyGeometry::D2::Ray.new([0, 0], [1, 1]) }
13
+ let(:r2) { EasyGeometry::D2::Ray.new([0, 0], [-1, 1]) }
14
+ let(:r3) { EasyGeometry::D2::Ray.new([0, 0], [1, 0]) }
15
+
16
+ describe '.new' do
17
+ it 'should raise type error if incorrect parameters' do
18
+ expect { described_class.new("1", 0) }.to raise_error(TypeError)
19
+ expect { described_class.new(nil, 0) }.to raise_error(TypeError)
20
+ expect { described_class.new({}, 0) }.to raise_error(TypeError)
21
+ end
22
+
23
+ it 'should raise argument error if two points are equal' do
24
+ expect { described_class.new([0, 0], [0, 0]) }.to raise_error(ArgumentError)
25
+ expect { described_class.new([1, 1], [1, 1]) }.to raise_error(ArgumentError)
26
+ expect { described_class.new(EasyGeometry::D2::Point.new(2, 2), EasyGeometry::D2::Point.new(2, 2)) }.to raise_error(ArgumentError)
27
+ end
28
+
29
+ it 'should create line' do
30
+ expect(described_class.new(p1, [1, 1])).to eq(l1)
31
+ expect(described_class.new([0, 0], p2)).to eq(l1)
32
+ expect(described_class.new(p1, p2)).to eq(l1)
33
+ expect(described_class.new([0, 0], [1, 1])).to eq(l1)
34
+ end
35
+ end
36
+
37
+ describe '#direction' do
38
+ it 'should return a correct vector' do
39
+ expect(l1.direction).to eq(EasyGeometry::D2::Vector.new(1, 1))
40
+ expect(l2.direction).to eq(EasyGeometry::D2::Vector.new(-1, 1))
41
+ end
42
+ end
43
+
44
+ describe '#angle_between' do
45
+ it 'should raise error if incorrect parameters' do
46
+ expect { l1.angle_between(1) }.to raise_error(TypeError)
47
+ expect { l1.angle_between("") }.to raise_error(TypeError)
48
+ expect { l1.angle_between({}) }.to raise_error(TypeError)
49
+ end
50
+
51
+ it 'should return a correct angle' do
52
+ expect(l1.angle_between(l2)).to eq(90 * Math::PI / 180)
53
+ expect(l1.angle_between(s2)).to eq(90 * Math::PI / 180)
54
+ expect(l1.angle_between(r2)).to eq(90 * Math::PI / 180)
55
+
56
+ expect(l1.angle_between(l1)).to eq(0)
57
+ expect(l1.angle_between(s1)).to eq(0)
58
+ expect(l1.angle_between(r1)).to eq(0)
59
+
60
+ expect(l1.angle_between(l3)).to eq((45 * Math::PI / 180))
61
+ expect(l1.angle_between(s3)).to eq((45 * Math::PI / 180))
62
+ expect(l1.angle_between(r3)).to eq((45 * Math::PI / 180))
63
+ end
64
+ end
65
+
66
+ describe '#parallel_to?' do
67
+ it 'should raise error if incorrect parameters' do
68
+ expect { l1.parallel_to?(1) }.to raise_error(TypeError)
69
+ expect { l1.parallel_to?("") }.to raise_error(TypeError)
70
+ expect { l1.parallel_to?({}) }.to raise_error(TypeError)
71
+ end
72
+
73
+ it 'should return true' do
74
+ expect(l1.parallel_to?(l1)).to be true
75
+ expect(l1.parallel_to?(s1)).to be true
76
+ expect(l1.parallel_to?(r1)).to be true
77
+ expect(l3.parallel_to?(described_class.new([6, 6], [12, 6]))).to be true
78
+ end
79
+
80
+ it 'should return false' do
81
+ expect(l1.parallel_to?(l2)).to be false
82
+ expect(l1.parallel_to?(s2)).to be false
83
+ expect(l1.parallel_to?(r2)).to be false
84
+ expect(l2.parallel_to?(l3)).to be false
85
+ expect(l3.parallel_to?(described_class.new([6, 6], [12, 6.00001]))).to be false
86
+ end
87
+ end
88
+
89
+ describe '#perpendicular_to?' do
90
+ it 'should raise error if incorrect parameters' do
91
+ expect { l1.perpendicular_to?(1) }.to raise_error(TypeError)
92
+ expect { l1.perpendicular_to?("") }.to raise_error(TypeError)
93
+ expect { l1.perpendicular_to?({}) }.to raise_error(TypeError)
94
+ end
95
+
96
+ it 'should return true' do
97
+ expect(l1.perpendicular_to?(l2)).to be true
98
+ expect(l1.perpendicular_to?(s2)).to be true
99
+ expect(l1.perpendicular_to?(r2)).to be true
100
+ expect(l3.perpendicular_to?(described_class.new(p1, [0, 1]))).to be true
101
+ end
102
+
103
+ it 'should return false' do
104
+ expect(l1.perpendicular_to?(l1)).to be false
105
+ expect(l1.perpendicular_to?(s1)).to be false
106
+ expect(l1.perpendicular_to?(r1)).to be false
107
+ expect(l1.perpendicular_to?(l3)).to be false
108
+ expect(l2.perpendicular_to?(l3)).to be false
109
+ end
110
+ end
111
+
112
+ describe '#similar_to?' do
113
+ it 'should raise error if incorrect parameters' do
114
+ expect { l1.similar_to?(1) }.to raise_error(TypeError)
115
+ expect { l1.similar_to?("") }.to raise_error(TypeError)
116
+ expect { l1.similar_to?({}) }.to raise_error(TypeError)
117
+ end
118
+
119
+ it 'should return true' do
120
+ expect(l1.similar_to?(described_class.new([2, 2], [4, 4]))).to be true
121
+ expect(l1.similar_to?(EasyGeometry::D2::Segment.new([2, 2], [4, 4]))).to be true
122
+ expect(l1.similar_to?(EasyGeometry::D2::Ray.new([2, 2], [4, 4]))).to be true
123
+ expect(l3.similar_to?(described_class.new([10, 0], [40, 0]))).to be true
124
+ end
125
+
126
+ it 'should return false' do
127
+ expect(l1.similar_to?(l2)).to be false
128
+ expect(l1.similar_to?(s2)).to be false
129
+ expect(l1.similar_to?(r2)).to be false
130
+ expect(l1.similar_to?(l3)).to be false
131
+ expect(l2.similar_to?(l3)).to be false
132
+ end
133
+ end
134
+
135
+ describe '#intersection' do
136
+ it 'should raise error if incorrect parameters' do
137
+ expect { l1.intersection(1) }.to raise_error(TypeError)
138
+ expect { l1.intersection("") }.to raise_error(TypeError)
139
+ expect { l1.intersection({}) }.to raise_error(TypeError)
140
+ end
141
+
142
+ context 'intersection with a point' do
143
+ it 'should return array with our point' do
144
+ expect(l1.intersection(p1)).to eq([p1])
145
+ expect(l1.intersection(p2)).to eq([p2])
146
+ expect(l1.intersection(EasyGeometry::D2::Point.new(2, 2))).to eq([EasyGeometry::D2::Point.new(2, 2)])
147
+ end
148
+
149
+ it 'should return empty array' do
150
+ expect(l2.intersection(p2)).to eq([])
151
+ expect(l3.intersection(p2)).to eq([])
152
+ end
153
+ end
154
+
155
+ context 'intersection with a linear entity which lies on our line' do
156
+ let(:s1) { EasyGeometry::D2::Segment.new([10, 10], [20, 20]) }
157
+ let(:r1) { EasyGeometry::D2::Ray.new([10, 10], [20, 20]) }
158
+
159
+ it 'should return array with self when intersection with line' do
160
+ expect(l1.intersection(l1)).to eq([l1])
161
+ expect(l2.intersection(l2)).to eq([l2])
162
+ expect(l3.intersection(l3)).to eq([l3])
163
+ expect(l1.intersection(described_class.new([10, 10], [20, 20]))).to eq([l1])
164
+ end
165
+
166
+
167
+ it 'should return array with linear entity when intersection with no line' do
168
+ expect(l1.intersection(s1)).to eq([s1])
169
+ expect(l1.intersection(r1)).to eq([r1])
170
+ end
171
+ end
172
+
173
+ context 'intersection with a linear entity which does not lie on our line' do
174
+ context 'intersection with parallel linear entity' do
175
+ it 'should return empty array' do
176
+ expect(l1.intersection(described_class.new([1, 0], [2, 1]))).to eq([])
177
+ expect(l1.intersection(EasyGeometry::D2::Segment.new([1, 0], [2, 1]))).to eq([])
178
+ expect(l3.intersection(described_class.new([0, 1], [1, 1]))).to eq([])
179
+ expect(l3.intersection(EasyGeometry::D2::Ray.new([0, 1], [1, 1]))).to eq([])
180
+ end
181
+ end
182
+
183
+ context 'intersection with not parallel linear entity' do
184
+ it 'should return array with point' do
185
+ expect(l1.intersection(l2)).to eq([p1])
186
+ expect(l1.intersection(l3)).to eq([p1])
187
+ expect(l3.intersection(described_class.new([7, 1], [9, 2]))).to eq([
188
+ EasyGeometry::D2::Point.new(5, 0)
189
+ ])
190
+ expect(l3.intersection(described_class.new([1, 7], [2, 9]))).to eq([
191
+ EasyGeometry::D2::Point.new(-2.5, 0)
192
+ ])
193
+ expect(l3.intersection(EasyGeometry::D2::Segment.new([0, 0], [1, 1]))).to eq([p1])
194
+ expect(l3.intersection(EasyGeometry::D2::Segment.new([-1, -1], [1, 1]))).to eq([p1])
195
+ expect(l3.intersection(EasyGeometry::D2::Ray.new([0, 0], [1, 1]))).to eq([p1])
196
+ expect(l3.intersection(EasyGeometry::D2::Ray.new([-1, -1], [1, 1]))).to eq([p1])
197
+ end
198
+
199
+ it 'should return empty array' do
200
+ expect(l3.intersection(EasyGeometry::D2::Segment.new([2, 2], [1, 1]))).to eq([])
201
+ expect(l3.intersection(EasyGeometry::D2::Segment.new([-2, -2], [-1, -1]))).to eq([])
202
+
203
+ expect(l3.intersection(EasyGeometry::D2::Ray.new([0, 0.001], [1, 1]))).to eq([])
204
+ end
205
+ end
206
+ end
207
+ end
208
+
209
+ describe '#parallel_line' do
210
+ it 'should raise error if incorrect parameters' do
211
+ expect { l1.parallel_line(1) }.to raise_error(TypeError)
212
+ expect { l1.parallel_line("") }.to raise_error(TypeError)
213
+ expect { l1.parallel_line({}) }.to raise_error(TypeError)
214
+ end
215
+
216
+ it 'should return a parallel line' do
217
+ expect(l3.parallel_line(p2).parallel_to?(l3)).to be true
218
+ end
219
+ end
220
+
221
+ describe '#perpendicular_line' do
222
+ it 'should raise error if incorrect parameters' do
223
+ expect { l1.perpendicular_line(1) }.to raise_error(TypeError)
224
+ expect { l1.perpendicular_line("") }.to raise_error(TypeError)
225
+ expect { l1.perpendicular_line({}) }.to raise_error(TypeError)
226
+ end
227
+
228
+ it 'should return a perpendicular line' do
229
+ expect(l3.perpendicular_line(p2).perpendicular_to?(l3)).to be true
230
+ end
231
+ end
232
+
233
+ describe '#perpendicular_segment' do
234
+ it 'should raise error if incorrect parameters' do
235
+ expect { l1.perpendicular_segment(1) }.to raise_error(TypeError)
236
+ expect { l1.perpendicular_segment("") }.to raise_error(TypeError)
237
+ expect { l1.perpendicular_segment({}) }.to raise_error(TypeError)
238
+ end
239
+
240
+ it 'should return the point if line contains this point' do
241
+ expect(l1.perpendicular_segment(p1)).to eq(p1)
242
+ expect(l2.perpendicular_segment(p1)).to eq(p1)
243
+ expect(l3.perpendicular_segment(p1)).to eq(p1)
244
+ end
245
+
246
+ it 'should return a perpendicular segment' do
247
+ expect(l2.perpendicular_segment(p2)).to eq(EasyGeometry::D2::Segment.new(p2, p1))
248
+ end
249
+ end
250
+
251
+ describe '#slope' do
252
+ it 'should return a number' do
253
+ expect(l1.slope).to eq(1)
254
+ expect(l3.slope).to eq(0)
255
+ expect(described_class.new(p1, [0, 2]).slope).to eq(BigDecimal('Infinity'))
256
+ end
257
+ end
258
+
259
+ describe '#span_test' do
260
+ it 'should raise error if incorrect parameters' do
261
+ expect { l1.span_test(1) }.to raise_error(TypeError)
262
+ expect { l1.span_test("") }.to raise_error(TypeError)
263
+ expect { l1.span_test({}) }.to raise_error(TypeError)
264
+ end
265
+
266
+ it 'should return correct number' do
267
+ expect(l1.span_test(p1)).to eq(0)
268
+ expect(l1.span_test(p2)).to eq(1)
269
+ expect(l1.span_test(EasyGeometry::D2::Point.new(-1, -1))).to eq(-1)
270
+ end
271
+ end
272
+
273
+ describe '#contains?' do
274
+ it 'should return true' do
275
+ expect(l1.contains?(p1)).to be true
276
+ expect(l1.contains?(p2)).to be true
277
+ expect(l1.contains?(EasyGeometry::D2::Point.new(100, 100))).to be true
278
+ expect(l1.contains?(EasyGeometry::D2::Segment.new(
279
+ [1000, 1000], [2000, 2000]
280
+ ))).to be true
281
+ expect(l1.contains?(EasyGeometry::D2::Ray.new(
282
+ [-1000, -1000], [2000, 2000]
283
+ ))).to be true
284
+ end
285
+
286
+ it 'should return false' do
287
+ expect(l1.contains?(EasyGeometry::D2::Point.new(2, 3))).to be false
288
+ expect(l1.contains?(EasyGeometry::D2::Point.new(0, 0.1))).to be false
289
+ expect(l1.contains?(EasyGeometry::D2::Segment.new(
290
+ [1000.1, 1000], [2000, 2000]
291
+ ))).to be false
292
+ expect(l1.contains?(EasyGeometry::D2::Ray.new(
293
+ [-1000, -1001], [2000, 2000]
294
+ ))).to be false
295
+ expect(l1.contains?(2)).to be false
296
+ expect(l1.contains?("")).to be false
297
+ end
298
+ end
299
+
300
+ describe '#distance' do
301
+ it 'should raise error if incorrect parameters' do
302
+ expect { l1.distance(1) }.to raise_error(TypeError)
303
+ expect { l1.distance("") }.to raise_error(TypeError)
304
+ expect { l1.distance({}) }.to raise_error(TypeError)
305
+ end
306
+
307
+ it 'should return zero if line contains point' do
308
+ expect(l1.distance(p1)).to eq(0)
309
+ expect(l1.distance(p2)).to eq(0)
310
+ expect(l2.distance(p1)).to eq(0)
311
+ expect(l3.distance(p1)).to eq(0)
312
+ end
313
+
314
+ it 'should return correct number' do
315
+ expect(l1.distance([-1, 1])).to eq(Math.sqrt(2))
316
+ expect(l1.distance([1, -1])).to eq(Math.sqrt(2))
317
+ expect(l3.distance([10, 10])).to eq(10)
318
+ end
319
+ end
320
+
321
+ describe '#==' do
322
+ it 'should return false if argument is not line' do
323
+ expect(l1 == p1).to be false
324
+ expect(l1 == '').to be false
325
+ expect(l1 == 2).to be false
326
+ expect(l1 == EasyGeometry::D2::Segment.new([0, 0], [1, 1])).to be false
327
+ end
328
+
329
+ it 'should return false if not equal' do
330
+ expect(l1 == l2).to be false
331
+ expect(l1 == l3).to be false
332
+ end
333
+
334
+ it 'should return false if equal' do
335
+ expect(l1 == l1).to be true
336
+ expect(l1 == EasyGeometry::D2::Line.new([-1, -1], [100, 100])).to be true
337
+ end
338
+ end
339
+ end
@@ -0,0 +1,211 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe EasyGeometry::D2::Point do
4
+ let(:p1) { described_class.new(0, 0) }
5
+ let(:p2) { described_class.new(1, 1) }
6
+ let(:p3) { described_class.new(3, 0) }
7
+ let(:p4) { described_class.new(2, 2) }
8
+ let(:p5) { described_class.new(-2, 2) }
9
+ let(:l1) { EasyGeometry::D2::Line.new(p1, p2) }
10
+
11
+ describe '.new' do
12
+ it 'should raise error if incorrect parameters' do
13
+ expect { described_class.new("1", 0) }.to raise_error(TypeError)
14
+ expect { described_class.new(nil, 0) }.to raise_error(TypeError)
15
+ expect { described_class.new({}, 0) }.to raise_error(TypeError)
16
+ end
17
+
18
+ it 'should convert coords to big decimal' do
19
+ expect(p2.x).to be_kind_of(Rational)
20
+ expect(p2.y).to be_kind_of(Rational)
21
+ end
22
+ end
23
+
24
+ describe '.project' do
25
+ it 'should raise error if incorrect parameters' do
26
+ expect { described_class.project(1, 0) }.to raise_error(TypeError)
27
+ expect { described_class.project(nil, "qwe") }.to raise_error(TypeError)
28
+ expect { described_class.project(p2, p1) }.to raise_error(ArgumentError)
29
+ end
30
+
31
+ it 'should be equal' do
32
+ expect(described_class.project(p2, p2)).to eq(p2)
33
+ expect(described_class.project(p2, p3)).to eq(described_class.new(1, 0))
34
+ expect(described_class.project(p3, p2)).to eq(described_class.new(1.5, 1.5))
35
+ end
36
+ end
37
+
38
+ describe '.is_collinear?' do
39
+ it 'should raise error if incorrect parameters' do
40
+ expect { described_class.is_collinear?(1, 2) }.to raise_error(TypeError)
41
+ end
42
+
43
+ it 'should return true' do
44
+ expect(described_class.is_collinear?()).to be true
45
+ expect(described_class.is_collinear?(p1)).to be true
46
+ expect(described_class.is_collinear?(p1, p2)).to be true
47
+ expect(described_class.is_collinear?(p1, p2, p2, p2)).to be true
48
+ expect(described_class.is_collinear?(p1, p2, p4)).to be true
49
+ end
50
+
51
+ it 'should return false' do
52
+ expect(described_class.is_collinear?(p1, p2, p3, p4)).to be false
53
+ expect(described_class.is_collinear?(p1, p2, p3)).to be false
54
+ end
55
+ end
56
+
57
+ describe '.affine_rank' do
58
+ it 'should raise error if incorrect parameters' do
59
+ expect { described_class.affine_rank(1, 2) }.to raise_error(TypeError)
60
+ end
61
+
62
+ it 'should return -1' do
63
+ expect(described_class.affine_rank()).to eq(-1)
64
+ end
65
+ # Other tests are meaningless because they test the Matrix class
66
+ end
67
+
68
+ describe '#dot' do
69
+ it 'should raise error if incorrect parameters' do
70
+ expect { p1.dot(1) }.to raise_error(TypeError)
71
+ expect { p1.dot("sd") }.to raise_error(TypeError)
72
+ expect { p1.dot(l1) }.to raise_error(TypeError)
73
+ end
74
+
75
+ it 'should be equal' do
76
+ expect(p1.dot(p2)).to eq(0)
77
+ expect(p2.dot(p4)).to eq(4)
78
+ expect(p2.dot(p5)).to eq(0)
79
+ end
80
+ end
81
+
82
+ describe '#zero?' do
83
+ it 'should return true' do
84
+ expect(p1.zero?).to be true
85
+ end
86
+
87
+ it 'should return false' do
88
+ expect(p2.zero?).to be false
89
+ expect(p3.zero?).to be false
90
+ expect(p5.zero?).to be false
91
+ end
92
+ end
93
+
94
+ describe '#==' do
95
+ it 'should return true' do
96
+ expect(p1 == p1).to be true
97
+ expect(p2 == p2).to be true
98
+ expect(p3 == p3).to be true
99
+ expect(p4 == p4).to be true
100
+ expect(p5 == p5).to be true
101
+ end
102
+
103
+ it 'should return false' do
104
+ expect(p1 == p2).to be false
105
+ expect(p3 == p2).to be false
106
+ expect(p4 == p1).to be false
107
+ expect(p1 == 2).to be false
108
+ expect(p1 == '').to be false
109
+ expect(p1 == {}).to be false
110
+ end
111
+ end
112
+
113
+ describe '#-' do
114
+ it 'should raise error if incorrect parameters' do
115
+ expect { p1 - 1 }.to raise_error(TypeError)
116
+ expect { p2 - '' }.to raise_error(TypeError)
117
+ expect { p2 - l1 }.to raise_error(TypeError)
118
+ end
119
+
120
+ it 'should be equal' do
121
+ expect(p1 - p2).to eq(described_class.new(-1, -1))
122
+ expect(p5 - p3).to eq(described_class.new(-5, 2))
123
+ expect(p5 - p5).to eq(described_class.new(0, 0))
124
+ end
125
+ end
126
+
127
+ describe '#+' do
128
+ it 'should raise error if incorrect parameters' do
129
+ expect { p1 + 1 }.to raise_error(TypeError)
130
+ expect { p2 + '' }.to raise_error(TypeError)
131
+ expect { p2 + l1 }.to raise_error(TypeError)
132
+ end
133
+
134
+ it 'should be equal' do
135
+ expect(p1 + p2).to eq(described_class.new(1, 1))
136
+ expect(p5 + p3).to eq(described_class.new(1, 2))
137
+ expect(p5 + p5).to eq(described_class.new(-4, 4))
138
+ end
139
+ end
140
+
141
+ describe '#*' do
142
+ it 'should raise error if incorrect parameters' do
143
+ expect { p1 * p1 }.to raise_error(TypeError)
144
+ expect { p2 * '' }.to raise_error(TypeError)
145
+ expect { p1 * l1 }.to raise_error(TypeError)
146
+ end
147
+
148
+ it 'should be equal' do
149
+ expect(p1 * 10).to eq(described_class.new(0, 0))
150
+ expect(p2 * 10).to eq(described_class.new(10, 10))
151
+ expect(p5 * -2).to eq(described_class.new(4, -4))
152
+ end
153
+ end
154
+
155
+ describe '#/' do
156
+ it 'should raise error if incorrect parameters' do
157
+ expect { p1 / p1 }.to raise_error(TypeError)
158
+ expect { p2 / '' }.to raise_error(TypeError)
159
+ expect { p1 / l1 }.to raise_error(TypeError)
160
+ end
161
+
162
+ it 'should be equal' do
163
+ expect(p1 / 10).to eq(described_class.new(0, 0))
164
+ expect(p2 / 10).to eq(described_class.new(0.1, 0.1))
165
+ expect(p5 / -2).to eq(described_class.new(1, -1))
166
+ end
167
+ end
168
+
169
+ describe '#distance' do
170
+ it 'should raise error if incorrect parameters' do
171
+ expect { p1.distance(1) }.to raise_error(TypeError)
172
+ expect { p1.distance('') }.to raise_error(TypeError)
173
+ expect { p1.distance(nil) }.to raise_error(TypeError)
174
+ end
175
+
176
+ it 'should be equal' do
177
+ expect(p1.distance(p2)).to eq(Math.sqrt(2))
178
+ expect(p1.distance(p4)).to eq(Math.sqrt(8))
179
+ expect(p3.distance(p5)).to eq(Math.sqrt(29))
180
+ end
181
+ end
182
+
183
+ describe '#intersection' do
184
+ it 'should raise error if incorrect parameters' do
185
+ expect { p1.intersection(1) }.to raise_error(TypeError)
186
+ expect { p1.intersection('') }.to raise_error(TypeError)
187
+ expect { p1.intersection(nil) }.to raise_error(TypeError)
188
+ end
189
+
190
+ it 'should be equal' do
191
+ expect(p1.intersection(described_class.new(0, 0))).to eq([p1])
192
+ expect(p1.intersection(p2)).to eq([])
193
+ end
194
+ end
195
+
196
+ describe '#midpoint' do
197
+ it 'should raise error if incorrect parameters' do
198
+ expect { p1.midpoint(1) }.to raise_error(TypeError)
199
+ expect { p1.midpoint('') }.to raise_error(TypeError)
200
+ expect { p1.midpoint(nil) }.to raise_error(TypeError)
201
+ expect { p1.midpoint(l1) }.to raise_error(TypeError)
202
+ end
203
+
204
+ it 'should be equal' do
205
+ expect(p1.midpoint(p1)).to eq(p1)
206
+ expect(p1.midpoint(p2)).to eq(described_class.new(0.5, 0.5))
207
+ expect(p1.midpoint(p3)).to eq(described_class.new(1.5, 0))
208
+ expect(p2.midpoint(p5)).to eq(described_class.new(-0.5, 1.5))
209
+ end
210
+ end
211
+ end