cartesius 0.0.1 → 1.0.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.
- 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.
|