cartesius 0.0.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/cartesius/circumference.rb +27 -36
- data/lib/cartesius/ellipse.rb +96 -66
- data/lib/cartesius/hyperbola.rb +130 -69
- data/lib/cartesius/line.rb +3 -3
- data/lib/cartesius/parabola.rb +15 -37
- data/lib/cartesius/point.rb +3 -15
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8ca7c08a027f0547ece43bf75d1d622aa7a59279
|
4
|
+
data.tar.gz: 9b95391ad0010c8dd2cb1eb11a37933e2fa74b2f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b141b69ced00426c9c461e07bec394bacf3a625058c68ee101caa3f8886c21711342a920d2adfd29fc3fadc2094a108354ca004ad47a891a5830f306d4370d6
|
7
|
+
data.tar.gz: b37537b3e28b9973c9d2981742cc52e6a2b181a1bc7342407af1e37d96fff7d343ed5199f4fce435c5d344909906a83d252541380e720a8cbb1d9c29bb5cb3f9
|
@@ -11,57 +11,56 @@ module Cartesius
|
|
11
11
|
# Conic
|
12
12
|
# Conic equation type: x^2 + y^2 + dx + ey + f = 0
|
13
13
|
def initialize(x:, y:, k:)
|
14
|
-
@x2_coeff, @y2_coeff, @x_coeff, @y_coeff, @k_coeff = 1, 1, x
|
14
|
+
@x2_coeff, @y2_coeff, @x_coeff, @y_coeff, @k_coeff = normalize(1, 1, x, y, k)
|
15
15
|
validation
|
16
16
|
end
|
17
17
|
|
18
|
-
def self.by_definition(
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
def self.by_definition(center:, radius:)
|
19
|
+
if radius <= 0
|
20
|
+
raise ArgumentError.new('Radius must be positive!')
|
21
|
+
end
|
22
22
|
|
23
|
-
|
23
|
+
build_by(center, radius)
|
24
24
|
end
|
25
25
|
|
26
|
-
def self.
|
27
|
-
|
26
|
+
def self.by_diameter(diameter:)
|
27
|
+
center = diameter.mid
|
28
|
+
radius = Rational(diameter.length, 2)
|
29
|
+
|
30
|
+
build_by(center, radius)
|
28
31
|
end
|
29
32
|
|
30
33
|
def self.by_points(point1:, point2:, point3:)
|
31
|
-
if point1 == point2 or point1 == point3 or point2 == point3
|
32
|
-
raise ArgumentError.new('Points must be distinct!')
|
33
|
-
end
|
34
|
-
|
35
|
-
line = Line.by_points(point1: point1, point2: point2)
|
36
|
-
if line.include?(point3)
|
37
|
-
raise ArgumentError.new('Points must not be aligned!')
|
38
|
-
end
|
39
|
-
|
40
34
|
alfa, beta, gamma = Cramer.solution3(
|
41
35
|
[point1.x, point1.y, 1],
|
42
36
|
[point2.x, point2.y, 1],
|
43
37
|
[point3.x, point3.y, 1],
|
44
38
|
[-(point1.x ** 2 + point1.y ** 2), -(point2.x ** 2 + point2.y ** 2), -(point3.x ** 2 + point3.y ** 2)]
|
45
39
|
)
|
46
|
-
|
47
40
|
self.new(x: alfa, y: beta, k: gamma)
|
41
|
+
rescue
|
42
|
+
raise ArgumentError.new('Invalid points!')
|
48
43
|
end
|
49
44
|
|
50
|
-
|
51
|
-
|
52
|
-
new(x: 0, y: 0, k: -1)
|
45
|
+
def self.goniometric
|
46
|
+
build_by(Point.origin, 1)
|
53
47
|
end
|
54
48
|
|
55
|
-
def
|
56
|
-
|
49
|
+
def goniometric?
|
50
|
+
self == Circumference.goniometric
|
57
51
|
end
|
58
52
|
|
59
53
|
def radius
|
60
54
|
Math.sqrt(a2)
|
61
55
|
end
|
62
56
|
|
63
|
-
def
|
64
|
-
|
57
|
+
def eccentricity
|
58
|
+
0
|
59
|
+
end
|
60
|
+
|
61
|
+
def congruent?(circumference)
|
62
|
+
circumference.instance_of?(Circumference) and
|
63
|
+
circumference.radius == self.radius
|
65
64
|
end
|
66
65
|
|
67
66
|
def == (circumference)
|
@@ -69,19 +68,11 @@ module Cartesius
|
|
69
68
|
circumference.center == self.center and circumference.radius == self.radius
|
70
69
|
end
|
71
70
|
|
72
|
-
def
|
73
|
-
|
74
|
-
return false
|
75
|
-
end
|
76
|
-
|
77
|
-
circumference.radius == self.radius
|
71
|
+
def self.build_by(center, radius)
|
72
|
+
self.new(x: -2 * center.x, y: -2 * center.y, k: center.x ** 2 + center.y ** 2 - radius.to_r ** 2)
|
78
73
|
end
|
79
74
|
|
80
|
-
|
81
|
-
equationfy(
|
82
|
-
'x^2' => @x2_coeff, 'y^2' => @y2_coeff, 'x' => @x_coeff, 'y' => @y_coeff, '1' => @k_coeff
|
83
|
-
)
|
84
|
-
end
|
75
|
+
private_class_method(:build_by)
|
85
76
|
|
86
77
|
private
|
87
78
|
|
data/lib/cartesius/ellipse.rb
CHANGED
@@ -11,8 +11,7 @@ module Cartesius
|
|
11
11
|
# Conic
|
12
12
|
# Conic equation type: ax^2 + by^2 + dx + ey + f = 0
|
13
13
|
def initialize(x2:, y2:, x:, y:, k:)
|
14
|
-
|
15
|
-
@x2_coeff, @y2_coeff, @x_coeff, @y_coeff, @k_coeff = x2.to_r, y2.to_r, x.to_r, y.to_r, k.to_r
|
14
|
+
@x2_coeff, @y2_coeff, @x_coeff, @y_coeff, @k_coeff = normalize(x2, y2, x, y, k)
|
16
15
|
validation
|
17
16
|
end
|
18
17
|
|
@@ -21,42 +20,61 @@ module Cartesius
|
|
21
20
|
raise ArgumentError.new('Focus points must be different!')
|
22
21
|
end
|
23
22
|
|
24
|
-
|
25
|
-
|
23
|
+
focal_axis = Segment.new(extreme1: focus1, extreme2: focus2)
|
24
|
+
if focal_axis.inclined?
|
25
|
+
raise ArgumentError.new('Focal axis must not be inclined!')
|
26
26
|
end
|
27
27
|
|
28
|
-
|
29
|
-
if distance <= focal_distance
|
28
|
+
if distance <= focal_axis.length
|
30
29
|
raise ArgumentError.new('Sum of distances must be greater than focal distance!')
|
31
30
|
end
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
if focus1.aligned_horizontally_with?(focus2)
|
32
|
+
c2 = Rational(focal_axis.length, 2) ** 2
|
33
|
+
if focal_axis.horizontal?
|
36
34
|
a2 = Rational(distance, 2) ** 2
|
37
35
|
b2 = a2 - c2
|
38
|
-
|
39
|
-
if focus1.aligned_vertically_with?(focus2)
|
36
|
+
else
|
40
37
|
b2 = Rational(distance, 2) ** 2
|
41
38
|
a2 = b2 - c2
|
42
39
|
end
|
43
40
|
|
44
|
-
|
41
|
+
center = focal_axis.mid
|
42
|
+
|
43
|
+
build_by(a2, b2, center)
|
45
44
|
end
|
46
45
|
|
47
|
-
def self.
|
48
|
-
if
|
49
|
-
raise ArgumentError.new('
|
46
|
+
def self.by_axes(major_axis:, minor_axis:)
|
47
|
+
if major_axis == minor_axis
|
48
|
+
raise ArgumentError.new('Axes must be different!')
|
50
49
|
end
|
51
50
|
|
52
|
-
if
|
53
|
-
raise ArgumentError.new('
|
51
|
+
if major_axis.inclined? or minor_axis.inclined?
|
52
|
+
raise ArgumentError.new('Axes must not be inclined!')
|
54
53
|
end
|
55
54
|
|
56
|
-
|
57
|
-
|
55
|
+
if major_axis.horizontal? and minor_axis.horizontal?
|
56
|
+
raise ArgumentError.new('Axes can not be both horizontal!')
|
57
|
+
end
|
58
58
|
|
59
|
-
|
59
|
+
if major_axis.vertical? and minor_axis.vertical?
|
60
|
+
raise ArgumentError.new('Axes can not be both vertical!')
|
61
|
+
end
|
62
|
+
|
63
|
+
if major_axis.mid != minor_axis.mid
|
64
|
+
raise ArgumentError.new('Axes must be the same mid point!')
|
65
|
+
end
|
66
|
+
|
67
|
+
if major_axis.horizontal?
|
68
|
+
a2 = Rational(major_axis.length, 2) ** 2
|
69
|
+
b2 = Rational(minor_axis.length, 2) ** 2
|
70
|
+
else
|
71
|
+
a2 = Rational(minor_axis.length, 2) ** 2
|
72
|
+
b2 = Rational(major_axis.length, 2) ** 2
|
73
|
+
end
|
74
|
+
|
75
|
+
center = major_axis.mid
|
76
|
+
|
77
|
+
build_by(a2, b2, center)
|
60
78
|
end
|
61
79
|
|
62
80
|
def self.by_points(center:, point1:, point2:)
|
@@ -74,74 +92,62 @@ module Cartesius
|
|
74
92
|
[1, 1]
|
75
93
|
)
|
76
94
|
rescue
|
77
|
-
raise ArgumentError.new('
|
95
|
+
raise ArgumentError.new('Center and points are not valid!')
|
78
96
|
end
|
79
97
|
|
80
98
|
a2 = Rational(1, alfa)
|
81
99
|
b2 = Rational(1, beta)
|
82
100
|
|
83
|
-
|
101
|
+
build_by(a2, b2, center)
|
84
102
|
end
|
85
103
|
|
86
104
|
def focus1
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
end
|
105
|
+
discriminating(
|
106
|
+
lambda {Point.new(x: center.x + cx, y: center.y)},
|
107
|
+
lambda {Point.new(x: center.x, y: center.y + cy)}
|
108
|
+
)
|
92
109
|
end
|
93
110
|
|
94
111
|
def focus2
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
def focal_distance
|
103
|
-
Point.distance(focus1, focus2)
|
104
|
-
end
|
105
|
-
|
106
|
-
def center
|
107
|
-
Point.new(x: centrum[:xc], y: centrum[:yc])
|
108
|
-
end
|
109
|
-
|
110
|
-
def sum_of_distances
|
111
|
-
if a2 > b2
|
112
|
-
2 * Math.sqrt(a2)
|
113
|
-
else
|
114
|
-
2 * Math.sqrt(b2)
|
115
|
-
end
|
112
|
+
discriminating(
|
113
|
+
lambda {Point.new(x: center.x - cx, y: center.y)},
|
114
|
+
lambda {Point.new(x: center.x, y: center.y - cy)}
|
115
|
+
)
|
116
116
|
end
|
117
117
|
|
118
|
-
def
|
119
|
-
|
118
|
+
def distance
|
119
|
+
discriminating(lambda {2 * a}, lambda {2 * b})
|
120
120
|
end
|
121
121
|
|
122
|
-
def
|
123
|
-
|
122
|
+
def focal_axis
|
123
|
+
Segment.new(extreme1: focus1, extreme2: focus2)
|
124
124
|
end
|
125
125
|
|
126
|
-
def
|
127
|
-
|
126
|
+
def major_axis
|
127
|
+
discriminating(
|
128
|
+
lambda {Segment.new(extreme1: Point.new(x: center.x - a, y: center.y), extreme2: Point.new(x: center.x + a, y: center.y))},
|
129
|
+
lambda {Segment.new(extreme1: Point.new(x: center.x, y: center.y - b), extreme2: Point.new(x: center.x, y: center.y + b))},
|
130
|
+
)
|
128
131
|
end
|
129
132
|
|
130
|
-
def
|
131
|
-
|
133
|
+
def minor_axis
|
134
|
+
discriminating(
|
135
|
+
lambda {Segment.new(extreme1: Point.new(x: center.x, y: center.y - b), extreme2: Point.new(x: center.x, y: center.y + b))},
|
136
|
+
lambda {Segment.new(extreme1: Point.new(x: center.x - a, y: center.y), extreme2: Point.new(x: center.x + a, y: center.y))}
|
137
|
+
)
|
132
138
|
end
|
133
139
|
|
134
140
|
def vertices
|
135
141
|
[
|
136
|
-
Point.new(x: center.x +
|
137
|
-
Point.new(x: center.x, y: center.y -
|
138
|
-
Point.new(x: center.x -
|
139
|
-
Point.new(x: center.x, y: center.y +
|
142
|
+
Point.new(x: center.x + a, y: center.y),
|
143
|
+
Point.new(x: center.x, y: center.y - b),
|
144
|
+
Point.new(x: center.x - a, y: center.y),
|
145
|
+
Point.new(x: center.x, y: center.y + b)
|
140
146
|
]
|
141
147
|
end
|
142
148
|
|
143
149
|
def eccentricity
|
144
|
-
Rational(
|
150
|
+
Rational(focal_axis.length, major_axis.length)
|
145
151
|
end
|
146
152
|
|
147
153
|
def congruent?(ellipse)
|
@@ -151,15 +157,15 @@ module Cartesius
|
|
151
157
|
|
152
158
|
def == (ellipse)
|
153
159
|
ellipse.instance_of?(Ellipse) and
|
154
|
-
ellipse.focus1 == self.focus1 and ellipse.focus2 == self.focus2 and ellipse.
|
160
|
+
ellipse.focus1 == self.focus1 and ellipse.focus2 == self.focus2 and ellipse.distance == self.distance
|
155
161
|
end
|
156
162
|
|
157
|
-
def
|
158
|
-
|
159
|
-
'x^2' => @x2_coeff, 'y^2' => @y2_coeff, 'x' => @x_coeff, 'y' => @y_coeff, '1' => @k_coeff
|
160
|
-
)
|
163
|
+
def self.build_by(a2, b2, center)
|
164
|
+
self.new(x2: b2, y2: a2, x: -2 * b2 * center.x, y: -2 * a2 * center.y, k: b2 * center.x ** 2 + a2 * center.y ** 2 - a2 * b2)
|
161
165
|
end
|
162
166
|
|
167
|
+
private_class_method(:build_by)
|
168
|
+
|
163
169
|
private
|
164
170
|
|
165
171
|
def validation
|
@@ -168,6 +174,30 @@ module Cartesius
|
|
168
174
|
end
|
169
175
|
end
|
170
176
|
|
177
|
+
def discriminating(horizontal_focus_type, vertical_focus_type)
|
178
|
+
if a2 > b2
|
179
|
+
horizontal_focus_type.call
|
180
|
+
else
|
181
|
+
vertical_focus_type.call
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def a
|
186
|
+
Math.sqrt(a2)
|
187
|
+
end
|
188
|
+
|
189
|
+
def b
|
190
|
+
Math.sqrt(b2)
|
191
|
+
end
|
192
|
+
|
193
|
+
def cx
|
194
|
+
Math.sqrt(a2 - b2)
|
195
|
+
end
|
196
|
+
|
197
|
+
def cy
|
198
|
+
Math.sqrt(b2 - a2)
|
199
|
+
end
|
200
|
+
|
171
201
|
end
|
172
202
|
|
173
203
|
end
|
data/lib/cartesius/hyperbola.rb
CHANGED
@@ -8,11 +8,15 @@ module Cartesius
|
|
8
8
|
class Hyperbola
|
9
9
|
include Determinator, Numerificator
|
10
10
|
|
11
|
-
|
11
|
+
RIGHT_POSITION = 1
|
12
|
+
UP_POSITION = -1
|
13
|
+
|
14
|
+
private_constant(:UP_POSITION)
|
15
|
+
private_constant(:RIGHT_POSITION)
|
16
|
+
|
12
17
|
# Conic equation type: ax^2 + by^2 + dx + ey + f = 0
|
13
18
|
def initialize(x2:, y2:, x:, y:, k:)
|
14
|
-
|
15
|
-
@x2_coeff, @y2_coeff, @x_coeff, @y_coeff, @k_coeff = x2.to_r, y2.to_r, x.to_r, y.to_r, k.to_r
|
19
|
+
@x2_coeff, @y2_coeff, @x_coeff, @y_coeff, @k_coeff = normalize(x2, y2, x, y, k)
|
16
20
|
validation
|
17
21
|
end
|
18
22
|
|
@@ -21,51 +25,65 @@ module Cartesius
|
|
21
25
|
raise ArgumentError.new('Focus points must be different!')
|
22
26
|
end
|
23
27
|
|
24
|
-
|
25
|
-
|
28
|
+
focal_axis = Segment.new(extreme1: focus1, extreme2: focus2)
|
29
|
+
if focal_axis.inclined?
|
30
|
+
raise ArgumentError.new('Focal axis must not be inclined!')
|
26
31
|
end
|
27
32
|
|
28
|
-
|
29
|
-
|
30
|
-
raise ArgumentError.new('Difference of distances must be less than focal distance!')
|
33
|
+
if distance >= focal_axis.length
|
34
|
+
raise ArgumentError.new('Difference between distances must be less than focal distance!')
|
31
35
|
end
|
32
36
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
a2 = Rational(distance, 2) ** 2
|
37
|
+
c2 = Rational(focal_axis.length, 2)**2
|
38
|
+
if focal_axis.horizontal?
|
39
|
+
a2 = Rational(distance, 2)**2
|
37
40
|
b2 = c2 - a2
|
38
|
-
position =
|
39
|
-
|
40
|
-
|
41
|
-
b2 = Rational(distance, 2) ** 2
|
41
|
+
position = RIGHT_POSITION
|
42
|
+
else
|
43
|
+
b2 = Rational(distance, 2)**2
|
42
44
|
a2 = c2 - b2
|
43
|
-
position =
|
45
|
+
position = UP_POSITION
|
44
46
|
end
|
45
47
|
|
46
|
-
|
48
|
+
center = focal_axis.mid
|
49
|
+
|
50
|
+
build_by(a2, b2, center, position)
|
47
51
|
end
|
48
52
|
|
49
|
-
def self.
|
50
|
-
if transverse_axis
|
51
|
-
raise ArgumentError.new('
|
53
|
+
def self.by_axes(transverse_axis:, not_transverse_axis:)
|
54
|
+
if transverse_axis == not_transverse_axis
|
55
|
+
raise ArgumentError.new('Axes must be different!')
|
52
56
|
end
|
53
57
|
|
54
|
-
|
55
|
-
raise ArgumentError.new('
|
58
|
+
if transverse_axis.inclined? or not_transverse_axis.inclined?
|
59
|
+
raise ArgumentError.new('Axes must not be inclined!')
|
56
60
|
end
|
57
61
|
|
58
|
-
if
|
59
|
-
|
60
|
-
b2 = transverse_axis ** 2
|
62
|
+
if transverse_axis.horizontal? and not_transverse_axis.horizontal?
|
63
|
+
raise ArgumentError.new('Axes can not be both horizontal!')
|
61
64
|
end
|
62
65
|
|
63
|
-
if
|
64
|
-
|
65
|
-
b2 = not_transverse_axis ** 2
|
66
|
+
if transverse_axis.vertical? and not_transverse_axis.vertical?
|
67
|
+
raise ArgumentError.new('Axes can not be both vertical!')
|
66
68
|
end
|
67
69
|
|
68
|
-
|
70
|
+
if transverse_axis.mid != not_transverse_axis.mid
|
71
|
+
raise ArgumentError.new('Axes must be the same mid point!')
|
72
|
+
end
|
73
|
+
|
74
|
+
if transverse_axis.horizontal?
|
75
|
+
a2 = Rational(transverse_axis.length, 2)**2
|
76
|
+
b2 = Rational(not_transverse_axis.length, 2)**2
|
77
|
+
position = RIGHT_POSITION
|
78
|
+
else
|
79
|
+
a2 = Rational(not_transverse_axis.length, 2)**2
|
80
|
+
b2 = Rational(transverse_axis.length, 2)**2
|
81
|
+
position = UP_POSITION
|
82
|
+
end
|
83
|
+
|
84
|
+
center = transverse_axis.mid
|
85
|
+
|
86
|
+
build_by(a2, b2, center, position)
|
69
87
|
end
|
70
88
|
|
71
89
|
def self.by_points(center:, vertex:, point:)
|
@@ -73,16 +91,15 @@ module Cartesius
|
|
73
91
|
raise ArgumentError.new('Points must be different!')
|
74
92
|
end
|
75
93
|
|
76
|
-
|
94
|
+
semi_axis = Segment.new(extreme1: center, extreme2: vertex)
|
95
|
+
if semi_axis.inclined?
|
77
96
|
raise ArgumentError.new('Vertex must be aligned with center!')
|
78
97
|
end
|
79
98
|
|
80
|
-
if
|
81
|
-
position =
|
82
|
-
|
83
|
-
|
84
|
-
if vertex.aligned_vertically_with?(center)
|
85
|
-
position = -1
|
99
|
+
if semi_axis.horizontal?
|
100
|
+
position = RIGHT_POSITION
|
101
|
+
else
|
102
|
+
position = UP_POSITION
|
86
103
|
end
|
87
104
|
|
88
105
|
shifted1 = Point.new(x: vertex.x - center.x, y: vertex.y - center.y)
|
@@ -90,53 +107,77 @@ module Cartesius
|
|
90
107
|
|
91
108
|
begin
|
92
109
|
alfa, beta = Cramer.solution2(
|
93
|
-
[shifted1.x
|
94
|
-
[shifted2.x
|
95
|
-
[
|
110
|
+
[shifted1.x**2, -shifted1.y**2],
|
111
|
+
[shifted2.x**2, -shifted2.y**2],
|
112
|
+
[position, position]
|
96
113
|
)
|
97
114
|
rescue
|
98
|
-
raise ArgumentError.new('
|
115
|
+
raise ArgumentError.new('Center, vertex and point are not valid!')
|
99
116
|
end
|
100
117
|
|
101
118
|
a2 = Rational(1, alfa)
|
102
119
|
b2 = Rational(1, beta)
|
103
120
|
|
104
|
-
|
121
|
+
build_by(a2, b2, center, position)
|
105
122
|
end
|
106
123
|
|
107
124
|
def focus1
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
return Point.new(x: center.x, y: center.y + Math.sqrt(a2 + b2))
|
113
|
-
end
|
125
|
+
discriminating(
|
126
|
+
lambda {Point.new(x: center.x + c, y: center.y)},
|
127
|
+
lambda {Point.new(x: center.x, y: center.y + c)}
|
128
|
+
)
|
114
129
|
end
|
115
130
|
|
116
131
|
def focus2
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
return Point.new(x: center.x, y: center.y - Math.sqrt(a2 + b2))
|
122
|
-
end
|
132
|
+
discriminating(
|
133
|
+
lambda {Point.new(x: center.x - c, y: center.y)},
|
134
|
+
lambda {Point.new(x: center.x, y: center.y - c)}
|
135
|
+
)
|
123
136
|
end
|
124
137
|
|
125
|
-
def
|
126
|
-
|
138
|
+
def distance
|
139
|
+
discriminating(lambda {2 * a}, lambda {2 * b})
|
127
140
|
end
|
128
141
|
|
129
|
-
def
|
130
|
-
|
142
|
+
def focal_axis
|
143
|
+
Segment.new(extreme1: focus1, extreme2: focus2)
|
131
144
|
end
|
132
145
|
|
133
|
-
def
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
146
|
+
def transverse_axis
|
147
|
+
discriminating(
|
148
|
+
lambda {Segment.new(extreme1: Point.new(x: center.x - a, y: center.y), extreme2: Point.new(x: center.x + a, y: center.y))},
|
149
|
+
lambda {Segment.new(extreme1: Point.new(x: center.x, y: center.y - b), extreme2: Point.new(x: center.x, y: center.y + b))},
|
150
|
+
)
|
151
|
+
end
|
152
|
+
|
153
|
+
def not_transverse_axis
|
154
|
+
discriminating(
|
155
|
+
lambda {Segment.new(extreme1: Point.new(x: center.x, y: center.y - b), extreme2: Point.new(x: center.x, y: center.y + b))},
|
156
|
+
lambda {Segment.new(extreme1: Point.new(x: center.x - a, y: center.y), extreme2: Point.new(x: center.x + a, y: center.y))}
|
157
|
+
)
|
158
|
+
end
|
159
|
+
|
160
|
+
def vertices
|
161
|
+
discriminating(
|
162
|
+
lambda {[Point.new(x: center.x - a, y: center.y), Point.new(x: center.x + a, y: center.y)]},
|
163
|
+
lambda {[Point.new(x: center.x, y: center.y - b), Point.new(x: center.x, y: center.y + b)]}
|
164
|
+
)
|
165
|
+
end
|
166
|
+
|
167
|
+
def eccentricity
|
168
|
+
Rational(focal_axis.length, transverse_axis.length)
|
169
|
+
end
|
170
|
+
|
171
|
+
def ascending_asymptote
|
172
|
+
Line.create(slope: Rational(b, a), known_term: center.y - center.x * Rational(b, a))
|
173
|
+
end
|
174
|
+
|
175
|
+
def descending_asymptote
|
176
|
+
Line.create(slope: -Rational(b, a), known_term: center.y + center.x * Rational(b, a))
|
177
|
+
end
|
178
|
+
|
179
|
+
def equilateral?
|
180
|
+
a2 == b2
|
140
181
|
end
|
141
182
|
|
142
183
|
def congruent?(hyperbola)
|
@@ -146,21 +187,41 @@ module Cartesius
|
|
146
187
|
|
147
188
|
def == (hyperbola)
|
148
189
|
hyperbola.instance_of?(Hyperbola) and
|
149
|
-
hyperbola.focus1 == self.focus1 and hyperbola.focus2 == self.focus2 and hyperbola.
|
190
|
+
hyperbola.focus1 == self.focus1 and hyperbola.focus2 == self.focus2 and hyperbola.distance == self.distance
|
150
191
|
end
|
151
192
|
|
193
|
+
def self.build_by(a2, b2, center, position)
|
194
|
+
self.new(x2: b2, y2: -a2, x: -2 * b2 * center.x, y: 2 * a2 * center.y, k: b2 * center.x ** 2 - a2 * center.y ** 2 + -position * a2 * b2)
|
195
|
+
end
|
196
|
+
|
197
|
+
private_class_method(:build_by)
|
198
|
+
|
152
199
|
private
|
153
200
|
|
154
201
|
def validation
|
155
|
-
|
156
202
|
if signum(@x2_coeff * @y2_coeff) >= 0 or determinator == @k_coeff
|
157
203
|
raise ArgumentError.new('Invalid coefficients!')
|
158
204
|
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def discriminating(horizontal_focus_type, vertical_focus_type)
|
208
|
+
if signum(determinator - @k_coeff) == 1
|
209
|
+
horizontal_focus_type.call
|
210
|
+
else
|
211
|
+
vertical_focus_type.call
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def a
|
216
|
+
Math.sqrt(a2)
|
217
|
+
end
|
159
218
|
|
219
|
+
def b
|
220
|
+
Math.sqrt(b2)
|
160
221
|
end
|
161
222
|
|
162
|
-
def
|
163
|
-
|
223
|
+
def c
|
224
|
+
Math.sqrt(a2 + b2)
|
164
225
|
end
|
165
226
|
|
166
227
|
end
|
data/lib/cartesius/line.rb
CHANGED
@@ -29,11 +29,11 @@ module Cartesius
|
|
29
29
|
raise ArgumentError.new('Points must be different!')
|
30
30
|
end
|
31
31
|
|
32
|
-
if point1.
|
32
|
+
if point1.y == point2.y
|
33
33
|
return horizontal(known_term: point1.y)
|
34
34
|
end
|
35
35
|
|
36
|
-
if point1.
|
36
|
+
if point1.x == point2.x
|
37
37
|
return vertical(known_term: point1.x)
|
38
38
|
end
|
39
39
|
|
@@ -143,7 +143,7 @@ module Cartesius
|
|
143
143
|
end
|
144
144
|
|
145
145
|
def == (line)
|
146
|
-
|
146
|
+
line.instance_of?(Line) and
|
147
147
|
line.slope == self.slope and line.known_term == self.known_term
|
148
148
|
end
|
149
149
|
|
data/lib/cartesius/parabola.rb
CHANGED
@@ -15,14 +15,6 @@ module Cartesius
|
|
15
15
|
validation
|
16
16
|
end
|
17
17
|
|
18
|
-
def self.unitary_convex
|
19
|
-
new(x2: 1, x: 0, k: 0)
|
20
|
-
end
|
21
|
-
|
22
|
-
def self.unitary_concave
|
23
|
-
new(x2: -1, x: 0, k: 0)
|
24
|
-
end
|
25
|
-
|
26
18
|
def self.by_definition(directrix:, focus:)
|
27
19
|
if directrix.include?(focus)
|
28
20
|
raise ArgumentError.new('Focus belongs to directrix!')
|
@@ -36,27 +28,10 @@ module Cartesius
|
|
36
28
|
b = -2 * a * focus.x
|
37
29
|
c = a * (focus.x ** 2) + focus.y - Rational(1, 4 * a)
|
38
30
|
|
39
|
-
self.new(x2:
|
40
|
-
end
|
41
|
-
|
42
|
-
def self.by_canonical(focus:, gap:)
|
43
|
-
if gap.zero?
|
44
|
-
raise ArgumentError.new('Gap must not be zero!')
|
45
|
-
end
|
46
|
-
|
47
|
-
a = gap
|
48
|
-
b = -2 * a * focus.x
|
49
|
-
c = (focus.x ** 2) + focus.y - Rational(1, 4 * a)
|
50
|
-
|
51
|
-
self.new(x2: -a, x: -b, k: -c)
|
31
|
+
self.new(x2: a, x: b, k: c)
|
52
32
|
end
|
53
33
|
|
54
34
|
def self.by_points(point1:, point2:, point3:)
|
55
|
-
|
56
|
-
if point1 == point2 or point1 == point3 or point2 == point3
|
57
|
-
raise ArgumentError.new('Points must be distinct!')
|
58
|
-
end
|
59
|
-
|
60
35
|
a, b, c = Cramer.solution3(
|
61
36
|
[point1.x ** 2, point1.x, 1],
|
62
37
|
[point2.x ** 2, point2.x, 1],
|
@@ -64,7 +39,9 @@ module Cartesius
|
|
64
39
|
[point1.y, point2.y, point3.y]
|
65
40
|
)
|
66
41
|
|
67
|
-
self.new(x2:
|
42
|
+
self.new(x2: a, x: b, k: c)
|
43
|
+
rescue
|
44
|
+
raise ArgumentError.new('Invalid points!')
|
68
45
|
end
|
69
46
|
|
70
47
|
def directrix
|
@@ -83,23 +60,24 @@ module Cartesius
|
|
83
60
|
Line.vertical(known_term: Rational(-@x_coeff, 2* @x2_coeff))
|
84
61
|
end
|
85
62
|
|
86
|
-
def
|
87
|
-
|
63
|
+
def eccentricity
|
64
|
+
@x2_coeff.abs
|
88
65
|
end
|
89
66
|
|
90
|
-
def
|
91
|
-
|
67
|
+
def to_equation
|
68
|
+
equationfy(
|
69
|
+
'x^2' => @x2_coeff, 'x' => @x_coeff, 'y' => -1, '1' => @k_coeff
|
70
|
+
)
|
92
71
|
end
|
93
72
|
|
94
|
-
def
|
73
|
+
def congruent?(parabola)
|
95
74
|
parabola.instance_of?(Parabola) and
|
96
|
-
parabola.
|
75
|
+
parabola.eccentricity == self.eccentricity
|
97
76
|
end
|
98
77
|
|
99
|
-
def
|
100
|
-
|
101
|
-
|
102
|
-
)
|
78
|
+
def == (parabola)
|
79
|
+
parabola.instance_of?(Parabola) and
|
80
|
+
parabola.focus == self.focus and parabola.directrix == self.directrix
|
103
81
|
end
|
104
82
|
|
105
83
|
private
|
data/lib/cartesius/point.rb
CHANGED
@@ -15,27 +15,15 @@ module Cartesius
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def self.distance(point1, point2)
|
18
|
-
Math.sqrt(
|
19
|
-
(point1.x - point2.x) ** 2 + (point1.y - point2.y) ** 2
|
20
|
-
)
|
18
|
+
Math.sqrt((point1.x - point2.x)** 2 + (point1.y - point2.y)** 2)
|
21
19
|
end
|
22
20
|
|
23
21
|
def origin?
|
24
22
|
self == Point.origin
|
25
23
|
end
|
26
24
|
|
27
|
-
def aligned_horizontally_with?(point)
|
28
|
-
@y == point.y
|
29
|
-
end
|
30
|
-
|
31
|
-
def aligned_vertically_with?(point)
|
32
|
-
@x == point.x
|
33
|
-
end
|
34
|
-
|
35
25
|
def distance_from(point)
|
36
|
-
Math.sqrt(
|
37
|
-
(@x - point.x) ** 2 + (@y - point.y) ** 2
|
38
|
-
)
|
26
|
+
Math.sqrt((@x - point.x)** 2 + (@y - point.y)** 2)
|
39
27
|
end
|
40
28
|
|
41
29
|
def to_coordinates
|
@@ -53,7 +41,7 @@ module Cartesius
|
|
53
41
|
end
|
54
42
|
|
55
43
|
def == (point)
|
56
|
-
|
44
|
+
point.instance_of?(Point) and
|
57
45
|
point.x == @x and point.y == @y
|
58
46
|
end
|
59
47
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cartesius
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mauro Quaglia
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-12-01 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: The cartesian plan and its elements.
|
14
14
|
email: mauroquaglia@libero.it
|
@@ -35,7 +35,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
35
35
|
requirements:
|
36
36
|
- - ">="
|
37
37
|
- !ruby/object:Gem::Version
|
38
|
-
version:
|
38
|
+
version: 2.4.0
|
39
39
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
40
40
|
requirements:
|
41
41
|
- - ">="
|
@@ -43,7 +43,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
43
43
|
version: '0'
|
44
44
|
requirements: []
|
45
45
|
rubyforge_project:
|
46
|
-
rubygems_version: 2.6.
|
46
|
+
rubygems_version: 2.6.10
|
47
47
|
signing_key:
|
48
48
|
specification_version: 4
|
49
49
|
summary: The cartesian coordinate system.
|