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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 95fd724a37b3fd9e2e072f649cd34ffcd6ade1bd
4
- data.tar.gz: 304ab894b81c52b1d02c63076be66879a20319f7
3
+ metadata.gz: 8ca7c08a027f0547ece43bf75d1d622aa7a59279
4
+ data.tar.gz: 9b95391ad0010c8dd2cb1eb11a37933e2fa74b2f
5
5
  SHA512:
6
- metadata.gz: 5f3b5b319332a590bcd796952e58328cbafa0b6857fea724bc796cbdc72520c715a167d063bf3510a5db5617cb52c49e55b75938c42c69c484a47a82a817471e
7
- data.tar.gz: 3abcc3dc0cdc72e7878dbb1c55cf7c4d887f1fe464e228083e993e0d11f4952ee9769c9afaf34cfc69212e51f848f56c32bc08b808cf1f2c259b941006bdc50d
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.to_r, y.to_r, k.to_r
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(focus:, radius:)
19
- alfa = -2 * focus.x
20
- beta = -2 * focus.y
21
- gamma = focus.x ** 2 + focus.y ** 2 - radius.to_r ** 2
18
+ def self.by_definition(center:, radius:)
19
+ if radius <= 0
20
+ raise ArgumentError.new('Radius must be positive!')
21
+ end
22
22
 
23
- self.new(x: alfa, y: beta, k: gamma)
23
+ build_by(center, radius)
24
24
  end
25
25
 
26
- def self.by_canonical(focus:, radius:)
27
- by_definition(focus: focus, radius: radius)
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
- def self.unitary
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 center
56
- Point.new(x: centrum[:xc], y: centrum[:yc])
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 unitary?
64
- self == Circumference.unitary
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 congruent?(circumference)
73
- unless circumference.instance_of?(self.class)
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
- def to_equation
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
 
@@ -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
- x2, y2, x, y, k = normalize(x2, y2, x, y, k)
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
- unless focus1.aligned_horizontally_with?(focus2) or focus1.aligned_vertically_with?(focus2)
25
- raise ArgumentError.new('Focus must be aligned to axis!')
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
- focal_distance = Point.distance(focus1, focus2)
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
- center = Segment.new(extreme1: focus1, extreme2: focus2).mid
34
- c2 = Rational(focal_distance, 2) ** 2
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
- end
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
- 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)
41
+ center = focal_axis.mid
42
+
43
+ build_by(a2, b2, center)
45
44
  end
46
45
 
47
- def self.by_canonical(center:, x_semi_axis:, y_semi_axis:)
48
- if x_semi_axis <= 0 or y_semi_axis <= 0
49
- raise ArgumentError.new('Semi axis length must be positive!')
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 x_semi_axis == y_semi_axis
53
- raise ArgumentError.new('Semi axis length must be different!')
51
+ if major_axis.inclined? or minor_axis.inclined?
52
+ raise ArgumentError.new('Axes must not be inclined!')
54
53
  end
55
54
 
56
- b2 = y_semi_axis ** 2
57
- a2 = x_semi_axis ** 2
55
+ if major_axis.horizontal? and minor_axis.horizontal?
56
+ raise ArgumentError.new('Axes can not be both horizontal!')
57
+ end
58
58
 
59
- 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)
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('No Ellipse for these points!')
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
- 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)
101
+ build_by(a2, b2, center)
84
102
  end
85
103
 
86
104
  def focus1
87
- if a2 > b2
88
- Point.new(x: center.x + Math.sqrt(a2 - b2), y: center.y)
89
- else
90
- Point.new(x: center.x, y: center.y + Math.sqrt(b2 - a2))
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
- if a2 > b2
96
- Point.new(x: center.x - Math.sqrt(a2 - b2), y: center.y)
97
- else
98
- Point.new(x: center.x, y: center.y - Math.sqrt(b2 - a2))
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 x_semi_axis_length
119
- Math.sqrt(a2)
118
+ def distance
119
+ discriminating(lambda {2 * a}, lambda {2 * b})
120
120
  end
121
121
 
122
- def y_semi_axis_length
123
- Math.sqrt(b2)
122
+ def focal_axis
123
+ Segment.new(extreme1: focus1, extreme2: focus2)
124
124
  end
125
125
 
126
- def major_semi_axis
127
- [x_semi_axis_length, y_semi_axis_length].max
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 minor_semi_axis
131
- [x_semi_axis_length, y_semi_axis_length].min
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 + x_semi_axis_length, y: center.y),
137
- Point.new(x: center.x, y: center.y - y_semi_axis_length),
138
- Point.new(x: center.x - x_semi_axis_length, y: center.y),
139
- Point.new(x: center.x, y: center.y + y_semi_axis_length)
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(focal_distance, 2 * major_semi_axis)
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.sum_of_distances == self.sum_of_distances
160
+ ellipse.focus1 == self.focus1 and ellipse.focus2 == self.focus2 and ellipse.distance == self.distance
155
161
  end
156
162
 
157
- def to_equation
158
- equationfy(
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
@@ -8,11 +8,15 @@ module Cartesius
8
8
  class Hyperbola
9
9
  include Determinator, Numerificator
10
10
 
11
- # Conic
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
- x2, y2, x, y, k = normalize(x2, y2, x, y, k)
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
- unless focus1.aligned_horizontally_with?(focus2) or focus1.aligned_vertically_with?(focus2)
25
- raise ArgumentError.new('Focus must be aligned to axis!')
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
- focal_distance = Point.distance(focus1, focus2)
29
- if distance >= focal_distance
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
- center = Segment.new(extreme1: focus1, extreme2: focus2).mid
34
- c2 = Rational(focal_distance, 2) ** 2
35
- if focus1.aligned_horizontally_with?(focus2)
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 = 1
39
- end
40
- if focus1.aligned_vertically_with?(focus2)
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 = -1
45
+ position = UP_POSITION
44
46
  end
45
47
 
46
- 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)
48
+ center = focal_axis.mid
49
+
50
+ build_by(a2, b2, center, position)
47
51
  end
48
52
 
49
- def self.by_canonical(center:, transverse_axis:, not_transverse_axis:, position:)
50
- if transverse_axis <= 0 or not_transverse_axis <= 0
51
- raise ArgumentError.new('Axis length must be positive!')
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
- unless [-1, 1].include?(position)
55
- raise ArgumentError.new('Position must be up or right!')
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 position == -1
59
- a2 = not_transverse_axis ** 2
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 position == 1
64
- a2 = transverse_axis ** 2
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
- 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)
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
- unless vertex.aligned_horizontally_with?(center) or vertex.aligned_vertically_with?(center)
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 vertex.aligned_horizontally_with?(center)
81
- position = 1
82
- end
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 ** 2, shifted1.y ** 2],
94
- [shifted2.x ** 2, shifted2.y ** 2],
95
- [1, 1]
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('No Hyperbola for these points!')
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
- 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)
121
+ build_by(a2, b2, center, position)
105
122
  end
106
123
 
107
124
  def focus1
108
- if position == 1
109
- return Point.new(x: center.x + Math.sqrt(a2 + b2), y: center.y)
110
- end
111
- if position == -1
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
- if position == 1
118
- return Point.new(x: center.x - Math.sqrt(a2 + b2), y: center.y)
119
- end
120
- if position == -1
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 focal_distance
126
- Point.distance(focus1, focus2)
138
+ def distance
139
+ discriminating(lambda {2 * a}, lambda {2 * b})
127
140
  end
128
141
 
129
- def center
130
- Point.new(x: centrum[:xc], y: centrum[:yc])
142
+ def focal_axis
143
+ Segment.new(extreme1: focus1, extreme2: focus2)
131
144
  end
132
145
 
133
- def difference_of_distances
134
- if position == 1
135
- return 2 * Math.sqrt(a2)
136
- end
137
- if position == -1
138
- return 2 * Math.sqrt(b2)
139
- end
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.difference_of_distances == self.difference_of_distances
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 position
163
- signum(determinator - @k_coeff)
223
+ def c
224
+ Math.sqrt(a2 + b2)
164
225
  end
165
226
 
166
227
  end
@@ -29,11 +29,11 @@ module Cartesius
29
29
  raise ArgumentError.new('Points must be different!')
30
30
  end
31
31
 
32
- if point1.aligned_horizontally_with?(point2)
32
+ if point1.y == point2.y
33
33
  return horizontal(known_term: point1.y)
34
34
  end
35
35
 
36
- if point1.aligned_vertically_with?(point2)
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
- congruent?(line) and
146
+ line.instance_of?(Line) and
147
147
  line.slope == self.slope and line.known_term == self.known_term
148
148
  end
149
149
 
@@ -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: -a, x: -b, k: -c)
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: -a, x: -b, k: -c)
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 unitary_convex?
87
- self == Parabola.unitary_convex
63
+ def eccentricity
64
+ @x2_coeff.abs
88
65
  end
89
66
 
90
- def unitary_concave?
91
- self == Parabola.unitary_concave
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 == (parabola)
73
+ def congruent?(parabola)
95
74
  parabola.instance_of?(Parabola) and
96
- parabola.focus == self.focus and parabola.directrix == self.directrix
75
+ parabola.eccentricity == self.eccentricity
97
76
  end
98
77
 
99
- def to_equation
100
- equationfy(
101
- 'x^2' => @x2_coeff, 'x' => @x_coeff, 'y' => @y_coeff, '1' => @k_coeff
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
@@ -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
- congruent?(point) and
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.1
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-07 00:00:00.000000000 Z
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: '0'
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.13
46
+ rubygems_version: 2.6.10
47
47
  signing_key:
48
48
  specification_version: 4
49
49
  summary: The cartesian coordinate system.