silicium 0.0.14 → 0.0.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +4 -0
  3. data/.gitignore +13 -11
  4. data/.rakeTasks +8 -0
  5. data/.travis.yml +17 -3
  6. data/CODE_OF_CONDUCT.md +74 -74
  7. data/Gemfile +8 -4
  8. data/LICENSE.txt +21 -21
  9. data/Makefile +269 -0
  10. data/README.md +588 -44
  11. data/Rakefile +17 -10
  12. data/bin/console +14 -14
  13. data/bin/setup +8 -8
  14. data/docs/Object.html +117 -0
  15. data/docs/README_md.html +142 -0
  16. data/docs/Silicium/Combinatorics.html +270 -0
  17. data/docs/Silicium/Dice/Polyhedron.html +315 -0
  18. data/docs/Silicium/Dice/PolyhedronSet.html +321 -0
  19. data/docs/Silicium/Dice.html +99 -0
  20. data/docs/Silicium/Error.html +106 -0
  21. data/docs/Silicium/Geometry/Line2dCanon.html +243 -0
  22. data/docs/Silicium/Geometry/VariablesOrderException.html +106 -0
  23. data/docs/Silicium/Geometry.html +940 -0
  24. data/docs/Silicium/GraphVisualizer.html +226 -0
  25. data/docs/Silicium/Graphs/GraphError.html +106 -0
  26. data/docs/Silicium/Graphs/OrientedGraph.html +901 -0
  27. data/docs/Silicium/Graphs/UnorientedGraph.html +237 -0
  28. data/docs/Silicium/Graphs.html +374 -0
  29. data/docs/Silicium/IntegralDoesntExistError.html +106 -0
  30. data/docs/Silicium/NumericalIntegration.html +521 -0
  31. data/docs/Silicium/Optimization.html +629 -0
  32. data/docs/Silicium/Plotter/Image.html +297 -0
  33. data/docs/Silicium/Plotter.html +186 -0
  34. data/docs/Silicium.html +101 -0
  35. data/docs/created.rid +9 -0
  36. data/docs/css/fonts.css +167 -0
  37. data/docs/css/rdoc.css +619 -0
  38. data/docs/fonts/Lato-Light.ttf +0 -0
  39. data/docs/fonts/Lato-LightItalic.ttf +0 -0
  40. data/docs/fonts/Lato-Regular.ttf +0 -0
  41. data/docs/fonts/Lato-RegularItalic.ttf +0 -0
  42. data/docs/fonts/SourceCodePro-Bold.ttf +0 -0
  43. data/docs/fonts/SourceCodePro-Regular.ttf +0 -0
  44. data/docs/images/add.png +0 -0
  45. data/docs/images/arrow_up.png +0 -0
  46. data/docs/images/brick.png +0 -0
  47. data/docs/images/brick_link.png +0 -0
  48. data/docs/images/bug.png +0 -0
  49. data/docs/images/bullet_black.png +0 -0
  50. data/docs/images/bullet_toggle_minus.png +0 -0
  51. data/docs/images/bullet_toggle_plus.png +0 -0
  52. data/docs/images/date.png +0 -0
  53. data/docs/images/delete.png +0 -0
  54. data/docs/images/find.png +0 -0
  55. data/docs/images/loadingAnimation.gif +0 -0
  56. data/docs/images/macFFBgHack.png +0 -0
  57. data/docs/images/package.png +0 -0
  58. data/docs/images/page_green.png +0 -0
  59. data/docs/images/page_white_text.png +0 -0
  60. data/docs/images/page_white_width.png +0 -0
  61. data/docs/images/plugin.png +0 -0
  62. data/docs/images/ruby.png +0 -0
  63. data/docs/images/tag_blue.png +0 -0
  64. data/docs/images/tag_green.png +0 -0
  65. data/docs/images/transparent.png +0 -0
  66. data/docs/images/wrench.png +0 -0
  67. data/docs/images/wrench_orange.png +0 -0
  68. data/docs/images/zoom.png +0 -0
  69. data/docs/index.html +134 -0
  70. data/docs/js/darkfish.js +84 -0
  71. data/docs/js/navigation.js +105 -0
  72. data/docs/js/navigation.js.gz +0 -0
  73. data/docs/js/search.js +110 -0
  74. data/docs/js/search_index.js +1 -0
  75. data/docs/js/search_index.js.gz +0 -0
  76. data/docs/js/searcher.js +229 -0
  77. data/docs/js/searcher.js.gz +0 -0
  78. data/docs/table_of_contents.html +697 -0
  79. data/lib/algebra.rb +452 -0
  80. data/lib/algebra_diff.rb +258 -0
  81. data/lib/geometry/figure.rb +62 -0
  82. data/lib/geometry.rb +290 -0
  83. data/lib/geometry3d.rb +270 -0
  84. data/lib/graph/dfs.rb +41 -0
  85. data/lib/graph/kruskal.rb +36 -0
  86. data/lib/graph/scc.rb +97 -0
  87. data/lib/graph.rb +350 -0
  88. data/lib/graph_visualizer.rb +286 -0
  89. data/lib/ml_algorithms.rb +181 -0
  90. data/lib/numerical_integration.rb +184 -0
  91. data/lib/optimization.rb +208 -0
  92. data/lib/plotter.rb +258 -0
  93. data/lib/polynomial_division.rb +132 -0
  94. data/lib/polynomial_interpolation.rb +94 -0
  95. data/lib/regression.rb +120 -0
  96. data/lib/silicium/adding.rb +37 -0
  97. data/lib/silicium/conversions.rb +23 -0
  98. data/lib/silicium/multi.rb +82 -0
  99. data/lib/silicium/sparse.rb +76 -0
  100. data/lib/silicium/sugar.rb +37 -0
  101. data/lib/silicium/trans.rb +26 -0
  102. data/lib/silicium/version.rb +3 -3
  103. data/lib/silicium.rb +29 -6
  104. data/lib/theory_of_probability.rb +240 -0
  105. data/lib/topological_sort.rb +50 -0
  106. data/oriented_graph.png +0 -0
  107. data/plot.png +0 -0
  108. data/silicium.gemspec +4 -3
  109. metadata +122 -12
@@ -0,0 +1,62 @@
1
+ module Silicium
2
+
3
+ module Geometry
4
+ class Figure
5
+ include Geometry
6
+ end
7
+
8
+ class Triangle < Figure
9
+
10
+ def initialize(p1, p2, p3)
11
+ s_p1p2 = distance_point_to_point2d(p1, p2)
12
+ s_p1p3 = distance_point_to_point2d(p1, p3)
13
+ s_p2p3 = distance_point_to_point2d(p2, p3)
14
+ if s_p1p2 + s_p2p3 <= s_p1p3 || s_p1p2 + s_p1p3 <= s_p2p3 || s_p2p3 + s_p1p3 <= s_p1p2
15
+ raise ArgumentError, 'Triangle does not exist'
16
+ else
17
+ @side_p1p2 = s_p1p2
18
+ @side_p1p3 = s_p1p3
19
+ @side_p2p3 = s_p2p3
20
+ end
21
+ end
22
+
23
+ def perimeter
24
+ @side_p1p2 + @side_p1p3 + @side_p2p3
25
+ end
26
+
27
+ def area
28
+ half_perimeter = perimeter / 2.0
29
+ Math.sqrt(half_perimeter * (half_perimeter - @side_p1p2) * (half_perimeter - @side_p2p3) * (half_perimeter - @side_p1p3))
30
+ end
31
+ end
32
+
33
+
34
+ ##
35
+ # TODO: Add a description
36
+ class Rectangle < Figure
37
+
38
+ def initialize(p1, p2, p3, p4)
39
+ raise ArgumentError, 'This is not a rectangle.' unless valid?(p1, p2, p3, p4)
40
+
41
+ @side1 = distance_point_to_point2d(p1, p2)
42
+ @side2 = distance_point_to_point2d(p2, p3)
43
+ @side3 = distance_point_to_point2d(p3, p4)
44
+ @side4 = distance_point_to_point2d(p4, p1)
45
+ end
46
+
47
+ ##
48
+ # Checks if input points form rectangle
49
+ def valid?(p1, p2, p3, p4)
50
+ distance_point_to_point2d(p1, p3) == distance_point_to_point2d(p2, p4)
51
+ end
52
+
53
+ def perimeter
54
+ @side1 + @side2 + @side3 + @side4
55
+ end
56
+
57
+ def area
58
+ @side1 * @side2
59
+ end
60
+ end
61
+ end
62
+ end
data/lib/geometry.rb ADDED
@@ -0,0 +1,290 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'geometry/figure'
4
+
5
+ module Silicium
6
+
7
+ module Geometry
8
+ ##
9
+ # Represents a point as two coordinates
10
+ # in two-dimensional space
11
+ Point = Struct.new(:x, :y)
12
+
13
+ ##
14
+ # Calculates the distance from given points in two-dimensional space
15
+ def distance_point_to_point2d(a, b)
16
+ Math.sqrt((b.x - a.x)**2 + (b.y - a.y)**2)
17
+ end
18
+
19
+ ##
20
+ # Class represents a line as equation Ax + By + C = 0
21
+ # in two-dimensional space
22
+ class Line2dCanon
23
+ attr_reader :x_coefficient
24
+ attr_reader :y_coefficient
25
+ attr_reader :free_coefficient
26
+
27
+ ##
28
+ # Initializes with two objects of type Point
29
+ def initialize(point1, point2)
30
+ raise ArgumentError, 'You need 2 different points' if point1.x.equal?(point2.x) && point1.y.equal?(point2.y)
31
+ if point1.x.equal?(point2.x)
32
+ @x_coefficient = 1
33
+ @y_coefficient = 0
34
+ @free_coefficient = - point1.x
35
+ else
36
+ slope_point = (point2.y - point1.y) / (point2.x - point1.x)
37
+ @x_coefficient = -slope_point
38
+ @y_coefficient = 1
39
+ @free_coefficient = - point1.y + slope_point * point1.x
40
+ end
41
+ end
42
+
43
+ # Initializes with coefficients
44
+ def initialize_with_coefficients(a, b, c)
45
+ raise ArgumentError, 'All coefficients cannot be 0 ' if a.equal?(0) && b.equal?(0) && (c.equal?(0) || !c.equal?(0))
46
+
47
+ @x_coefficient = a
48
+ @y_coefficient = b
49
+ @free_coefficient = c
50
+ end
51
+
52
+ ##
53
+ # Checks the point lies on the line or not
54
+ def point_is_on_line?(point)
55
+ ((@x_coefficient * point.x + @y_coefficient * point.y + @free_coefficient) - 0.0).abs < 0.0001
56
+ end
57
+
58
+ # Checks if two lines are parallel
59
+ def parallel?(other_line)
60
+ @x_coefficient.equal?(other_line.x_coefficient) && @y_coefficient.equal?(other_line.y_coefficient)
61
+ end
62
+
63
+ ##
64
+ # Checks if two lines are intersecting
65
+ def intersecting?(other_line)
66
+ @x_coefficient != other_line.x_coefficient || @y_coefficient != other_line.y_coefficient
67
+ end
68
+
69
+ ##
70
+ # Checks if two lines are perpendicular
71
+ def perpendicular?(other_line)
72
+ (@x_coefficient * other_line.x_coefficient).equal?(- @y_coefficient * other_line.y_coefficient)
73
+ end
74
+
75
+ ##
76
+ # Checking if the point is on a segment
77
+ def check_point_on_segment(point)
78
+ (@x_coefficient * point.x + @y_coefficient * point.y + @free_coefficient) - 0.0 <= 0.0001
79
+ end
80
+
81
+ ##
82
+ # Returns a point of intersection of two lines
83
+ # If not intersecting returns nil
84
+ def intersection_point(other_line)
85
+ return nil unless intersecting?(other_line)
86
+
87
+ divisor = @x_coefficient * other_line.y_coefficient - other_line.x_coefficient * @y_coefficient
88
+ x = (@y_coefficient * other_line.free_coefficient - other_line.y_coefficient * @free_coefficient) / divisor
89
+ y = (@free_coefficient * other_line.x_coefficient - other_line.free_coefficient * @x_coefficient) / divisor
90
+ Point.new(x, y)
91
+ end
92
+
93
+ ##
94
+ # Returns distance between lines
95
+ def distance_to_line(other_line)
96
+ return 0 if intersecting?(other_line)
97
+
98
+ (@free_coefficient - other_line.free_coefficient).abs / Math.sqrt(@x_coefficient**2 + @y_coefficient**2)
99
+ end
100
+
101
+ ##
102
+ # The distance from a point to a line on a plane
103
+ # return 0 if the equation does not define a line.
104
+ def distance_point_to_line(point)
105
+ return 0 if @x_coefficient.eql?(0) && @y_coefficient.eql?(0)
106
+
107
+ res = (@x_coefficient * point.x + @y_coefficient * point.y + @free_coefficient).abs
108
+ res / Math.sqrt(@x_coefficient**2 + @y_coefficient**2).to_f
109
+ end
110
+ ##
111
+ # Check if array of points is on the same line
112
+ def array_of_points_is_on_line(array)
113
+ raise ArgumentError, 'Array is empty!' if array.length == 0
114
+ res = Array.new
115
+ for i in 0..array.size-1 do
116
+ res.push(point_is_on_line?(array[i]))
117
+ end
118
+ res
119
+ end
120
+
121
+ ##
122
+ # The distance between parallel lines
123
+ def distance_between_parallel_lines(other_line)
124
+ raise ArgumentError, 'Lines are not parallel' if !parallel?(other_line)
125
+
126
+ (other_line.free_coefficient - @free_coefficient).abs / Math.sqrt(@x_coefficient**2 + @y_coefficient**2)
127
+ end
128
+ end
129
+
130
+ ##
131
+ # Function for checking sign of number
132
+ def sign(integer)
133
+ integer >= 0 ? 1 : -1
134
+ end
135
+ # The distance from a point to a line on a plane
136
+ # The line is defined by two points
137
+ # https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
138
+ def distance_point_line2d(p1, p2, a)
139
+ line_segment_length = distance_point_to_point2d(p1, p2)
140
+ ((p2.y - p1.y) * a.x - (p2.x - p1.x) * a.y + p2.x * p1.y - p2.y * p1.x).abs / (line_segment_length * 1.0)
141
+ end
142
+
143
+ ##
144
+ # The distance from a point to a line on a plane
145
+ # Normalized equation of the line
146
+ def distance_point_line_normalized2d(a, b, c, p)
147
+ (p.x * a + p.y * b - c).abs
148
+ end
149
+
150
+ def oriented_area(a, b, c)
151
+ a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y)
152
+ end
153
+
154
+ ##
155
+ # Determines if a clockwise crawl is performed
156
+ # for defined order of points
157
+ def clockwise(a, b, c)
158
+ oriented_area(a, b, c).negative?
159
+ end
160
+
161
+ ##
162
+ # Determines if a counter-clockwise crawl is
163
+ # performed for defined order of points
164
+ def counter_clockwise(a, b, c)
165
+ oriented_area(a, b, c).positive?
166
+ end
167
+
168
+ def not_polygon?(points)
169
+ points.empty? || points.size == 1 || points.size == 2
170
+ end
171
+
172
+ def put_point_in_part(part, point, direction)
173
+ direction = method(direction)
174
+ part.pop while part.size >= 2 && !direction.call(part[part.size - 2], part[part.size - 1], point)
175
+ part.push(point)
176
+ end
177
+
178
+ ##
179
+ # Returns an array containing points that are included
180
+ # in the minimal convex hull for a given array of points
181
+ # https://e-maxx.ru/algo/convex_hull_graham
182
+ def minimal_convex_hull_2d(points)
183
+ return points if not_polygon?(points)
184
+
185
+ points.sort_by! { |p| [p.x, p.y] }
186
+ first = points[0]
187
+ last = points.last
188
+ up = [first]
189
+ down = [first]
190
+
191
+ (1...points.size).each do |i|
192
+ point = points[i]
193
+ is_last = i == points.size - 1
194
+ put_point_in_part(up, point, :clockwise) if is_last || clockwise(first, point, last)
195
+ put_point_in_part(down, point, :counter_clockwise) if is_last || counter_clockwise(first, point, last)
196
+ end
197
+ up + down[1...-1]
198
+ end
199
+
200
+ def process_cf(line_equation, variable)
201
+ if line_equation.include?(variable)
202
+ before = line_equation.index('/') + 1
203
+ after = line_equation.index('=')
204
+ line_equation.slice(before..after).gsub('=', '').sub('*', '').gsub('(', '').gsub(')', '').to_f
205
+ else
206
+ 0.0
207
+ end
208
+ end
209
+
210
+ def cut_by_eq(line_equation)
211
+ line_equation.slice(line_equation.index('='), line_equation.length).sub('=', '')
212
+ end
213
+
214
+ def process_line_by_coordinates(line_equation, func)
215
+ copy_line = insert_eq(line_equation)
216
+ func = method(func)
217
+ res = []
218
+ res[0] = func.call(copy_line, 'x')
219
+ copy_line = cut_by_eq(copy_line)
220
+ res[1] = func.call(copy_line, 'y')
221
+ copy_line = cut_by_eq(copy_line)
222
+ res[2] = func.call(copy_line, 'z')
223
+ res
224
+ end
225
+
226
+
227
+
228
+ class VariablesOrderException < RuntimeError
229
+ end
230
+
231
+ def needed_variables_order?(before, after)
232
+ before < after
233
+ end
234
+
235
+ def process_free_member(line_equation, variable)
236
+ if line_equation.include?(variable)
237
+ before = line_equation.index(variable) + 1
238
+ after = line_equation.index('/')
239
+
240
+ throw VariablesOrderException unless needed_variables_order?(before, after)
241
+
242
+ line_equation.slice(before..after).gsub('/', '').to_f * -1
243
+ else
244
+ 0.0
245
+ end
246
+ end
247
+
248
+
249
+
250
+ def vectors_product(v1, v2)
251
+ res = Array.new(3)
252
+ (0..2).each do |i|
253
+ res[i] = v1[(i + 1) % 3] * v2[(i + 2) % 3] - v1[(i + 2) % 3] * v2[(i + 1) % 3]
254
+ end
255
+ res
256
+ end
257
+
258
+ def vector_length(vector)
259
+ Math.sqrt(vector[0]**2 + vector[1]**2 + vector[2]**2)
260
+ end
261
+
262
+
263
+
264
+ # Closest pair of points_________________________
265
+ # find minimum distance between two points in set
266
+ def brute_min(points, current = Float::INFINITY)
267
+ return current if points.length < 2
268
+
269
+ head = points[0]
270
+ points.delete_at(0)
271
+ new_min = points.map { |x| distance_point_to_point2d(head, x)}.min
272
+ new_сurrent = [new_min, current].min
273
+ brute_min(points, new_сurrent)
274
+ end
275
+
276
+ def divide_min(points)
277
+ half = points.length / 2
278
+ points.sort_by! { |p| [p.x, p.y] }
279
+ minimum = [brute_min(points[0..half]), brute_min(points[half..points.length])].min
280
+ near_line = points.select { |x| x > half - minimum and x < half + minimum}
281
+ min([brute_min(near_line), minimum])
282
+ end
283
+
284
+ def insert_eq(line_equation)
285
+ line_equation.gsub(' ', '').insert(line_equation.length, '=')
286
+ end
287
+ end
288
+ end
289
+
290
+
data/lib/geometry3d.rb ADDED
@@ -0,0 +1,270 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'geometry/figure'
4
+
5
+ module Silicium
6
+
7
+ module Geometry3d
8
+ ##
9
+ # Represents a point as three coordinates
10
+ # in three-dimensional space
11
+ Point3d = Struct.new(:x, :y, :z)
12
+
13
+ ##
14
+ # Calculates the distance from given points in three-dimensional space
15
+ def distance_point_to_point3d(a, b)
16
+ Math.sqrt((b.x - a.x)**2 + (b.y - a.y)**2 + (b.z - a.z)**2)
17
+ end
18
+
19
+ ##
20
+ # Class represents a plane as equation Ax + By + Cz+D = 0
21
+ # in two-dimensional space
22
+ class Plane3d
23
+ attr_reader :x_coefficient
24
+ attr_reader :y_coefficient
25
+ attr_reader :z_coefficient
26
+ attr_reader :free_coefficient
27
+
28
+ # Initializes with three objects of type Point
29
+ def initialize(point1, point2, point3)
30
+ vector1 = Vector3d.new(point1)
31
+ norm = vector1.norm_vector(point2, point3)
32
+ @x_coefficient = norm.x
33
+ @y_coefficient = norm.y
34
+ @z_coefficient = norm.z
35
+ @free_coefficient = -point1.x * norm.x + (-point1.y * norm.y) + (-point1.z * norm.z)
36
+ end
37
+
38
+ ##
39
+ # Initializes with coefficients
40
+ def initialize_with_coefficients(a, b, c, d)
41
+ raise ArgumentError, 'All coefficients cannot be 0 ' if a.equal?(0) && b.equal?(0) && c.equal?(0) && (d.equal?(0) || !d.equal?(0))
42
+
43
+ @x_coefficient = a
44
+ @y_coefficient = b
45
+ @z_coefficient = c
46
+ @free_coefficient = d
47
+ end
48
+
49
+ ##
50
+ # check if the points isn't on the same line
51
+ def point_is_on_line?(point1, point2, point3)
52
+ check_p1 = @x_coefficient * point1.x + @y_coefficient * point1.y + @z_coefficient * point1.z + @free_coefficient
53
+ check_p2 = @x_coefficient * point2.x + @y_coefficient * point2.y + @z_coefficient * point2.z + @free_coefficient
54
+ check_p3 = @x_coefficient * point3.x + @y_coefficient * point3.y + @z_coefficient * point3.z + @free_coefficient
55
+ check_p1.equal?(0) && check_p2.equal?(0) && check_p3.equal?(0)
56
+ end
57
+
58
+ # check if the point isn't on the plane
59
+ def point_is_on_plane?(point)
60
+ (@x_coefficient * point.x + @y_coefficient * point.y + @z_coefficient * point.z + @free_coefficient).equal?(0)
61
+ end
62
+
63
+ # Checks if two planes are parallel in 3-dimensional space
64
+ def parallel?(other_plane)
65
+ v1 = Vector3d.new(Point3d.new(@x_coefficient, @y_coefficient, @z_coefficient))
66
+ v2 = Vector3d.new(Point3d.new(other_plane.x_coefficient, other_plane.y_coefficient, other_plane.z_coefficient))
67
+ v1.collinear?(v2)
68
+ end
69
+
70
+ ##
71
+ # Checks if two planes are intersecting in 3-dimensional space
72
+ def intersecting?(other_plane)
73
+ check_x = @x_coefficient != other_plane.x_coefficient
74
+ check_y = @y_coefficient != other_plane.y_coefficient
75
+ check_z = @z_coefficient != other_plane.z_coefficient
76
+ check_x || check_y || check_z
77
+ end
78
+
79
+ ##
80
+ # Checks if two planes are perpendicular
81
+ def perpendicular?(other_plane)
82
+ check_x = @x_coefficient * other_plane.x_coefficient
83
+ check_y = @y_coefficient * other_plane.y_coefficient
84
+ check_z = @z_coefficient * other_plane.z_coefficient
85
+ (check_x + check_y + check_z).equal?(0)
86
+ end
87
+
88
+ ##
89
+ # The distance between parallel planes
90
+ def distance_between_parallel_planes(other_plane)
91
+ raise 'Planes are not parallel' if !parallel?(other_plane)
92
+
93
+ free = (other_plane.free_coefficient - @free_coefficient).abs
94
+ free / sqrt(@x_coefficient**2 + @y_coefficient**2 + @z_coefficient**2)
95
+ end
96
+
97
+ ##
98
+ # The distance from a point to a plane
99
+ #
100
+ def distance_point_to_plane(point)
101
+ norm = 1 / Math.sqrt(@x_coefficient**2 + @y_coefficient**2 + @z_coefficient**2)
102
+ (@x_coefficient * norm * point.x + @y_coefficient * norm * point.y +
103
+ @z_coefficient * norm * point.z + @free_coefficient * norm).abs
104
+ end
105
+ end
106
+ ##
107
+ # Class represents vector
108
+ # in three-dimensional space
109
+ class Vector3d
110
+ attr_reader :x
111
+ attr_reader :y
112
+ attr_reader :z
113
+
114
+ ##
115
+ # Initializes with one objects of type Point3d
116
+ # 2nd point is (0,0,0)
117
+ def initialize(point)
118
+ @x = point.x
119
+ @y = point.y
120
+ @z = point.z
121
+ end
122
+
123
+ ##
124
+ # Checks if vector is zero vector
125
+ def zero_vector?
126
+ (@x.eql?(0) && @y.eql?(0) && @z.eql?(0)).eql?(true) ? true : false
127
+ end
128
+
129
+ ##
130
+ # Returns length of the vector
131
+ def length
132
+ Math.sqrt(@x**2 + @y**2 + @z**2)
133
+ end
134
+
135
+ ##
136
+ # Add one vector to another
137
+ def addition!(other_vector)
138
+ @x += other_vector.x
139
+ @y += other_vector.y
140
+ @z += other_vector.z
141
+ end
142
+
143
+ ##
144
+ # Sub one vector from another
145
+ def subtraction!(other_vector)
146
+ @x -= other_vector.x
147
+ @y -= other_vector.y
148
+ @z -= other_vector.z
149
+ end
150
+
151
+ ##
152
+ # Mult vector by number
153
+ def multiplication_by_number!(r)
154
+ @x *= r
155
+ @y *= r
156
+ @z *= r
157
+ end
158
+
159
+ ##
160
+ # Returns scalar multiplication of 2 vectors
161
+ def scalar_multiplication(other_vector)
162
+ x * other_vector.x + y * other_vector.y + z * other_vector.z
163
+ end
164
+
165
+ ##
166
+ # Returns cos between two vectors
167
+ def cos_between_vectors(other_vector)
168
+ scalar_multiplication(other_vector) / (length * other_vector.length).to_f
169
+ end
170
+
171
+ ##
172
+ # Returns vector multiplication of 2 vectors
173
+ def vector_multiplication(other_vector)
174
+ x = @y * other_vector.z - @z * other_vector.y
175
+ y = @z * other_vector.x - @x * other_vector.z
176
+ z = @x * other_vector.y - @y * other_vector.x
177
+ Vector3d.new(Point3d.new(x, y, z))
178
+ end
179
+
180
+ ##
181
+ # Find normal vector
182
+ ##
183
+ # vector mult
184
+ def norm_vector(point2, point3)
185
+ point1 = Point3d.new(@x, @y, @z)
186
+ # checking if the points isn't on the same line
187
+ # finding vector between points 1 and 2 ;1 and 3
188
+ vector12 = Vector3d.new(Point3d.new(point2.x - point1.x, point2.y - point1.y, point2.z - point1.z))
189
+ vector13 = Vector3d.new(Point3d.new(point3.x - point1.x, point3.y - point1.y, point3.z - point1.z))
190
+ # vector13=vector1.scalar_multiplication(vector3)
191
+ x = vector12.y * vector13.z - vector12.z * vector13.y
192
+ y = -(vector12.x * vector13.z - vector12.z * vector13.x)
193
+ z = vector12.x * vector13.y - vector12.y * vector13.x
194
+ Vector3d.new(Point3d.new(x, y, z))
195
+ end
196
+
197
+ ##
198
+ # Function for checking sign of number
199
+ def sign(integer)
200
+ integer >= 0 ? 1 : -1
201
+ end
202
+
203
+ ##
204
+ # help function for collinear function
205
+ def help_check(vector2, x, y, z)
206
+ check1 = x * sign(vector2.x) * sign(@x) == y * sign(vector2.y) * sign(@y)
207
+ check2 = x * sign(vector2.x) * sign(@x) == z * sign(vector2.z) * sign(@z)
208
+ check3 = z * sign(vector2.z) * sign(@z) == y * sign(vector2.y) * sign(@y)
209
+ check1 && check2 && check3
210
+ end
211
+ ##
212
+ # helps to divide correctly
213
+ def helper(value1, value2)
214
+ result = 0
215
+ if value1 > value2
216
+ result = value1 / value2
217
+ else
218
+ result = value2 / value1
219
+ end
220
+ result
221
+ end
222
+
223
+ # Check if two vectors are collinear
224
+ def collinear?(vector2)
225
+ x1 = (vector2.x).abs
226
+ y1 = (vector2.y).abs
227
+ z1 = (vector2.z).abs
228
+ x = helper(x1,@x.abs)
229
+ y = helper(y1,@y.abs)
230
+ z = helper(z1,@z.abs)
231
+ help_check(vector2, x, y, z)
232
+ end
233
+ end
234
+
235
+ ##
236
+ # Creates an array- directing vector in three-dimensional space .
237
+ # The equation is specified in the canonical form.
238
+ # Example, (x-0) / 26 = (y + 300) / * (- 15) = (z-200) / 51
239
+ #
240
+ # Important: mandatory order of variables: x, y, z
241
+ def directing_vector3d(line_equation)
242
+ process_line_by_coordinates(line_equation, :process_cf)
243
+ end
244
+
245
+ ##
246
+ # Creates an array of coordinates of the point ([x, y, z] on the line
247
+ # given by the equation in the canonical form.
248
+ # Example, (x-0) / 26 = (y + 300) / * (- 15) = (z-200) / 51
249
+ #
250
+ # Important: mandatory order of variables: x, y, z
251
+ def height_point_3d(line_equation)
252
+ process_line_by_coordinates(line_equation, :process_free_member)
253
+ end
254
+
255
+ ##
256
+ # Calculates the distance from a point given by a Point3d structure
257
+ # to a straight line given by a canonical equation.
258
+ # Example, (x-0) / 26 = (y + 300) / * (- 15) = (z-200) / 51
259
+ #
260
+ # Important: mandatory order of variables: x, y, z
261
+ def point_to_line_distance_3d(point, line_eq)
262
+ dir_vector = directing_vector3d(line_eq)
263
+ line_point = height_point_3d(line_eq)
264
+ height_vector = [line_point[0] - point.x, line_point[1] - point.y, line_point[2] - point.z]
265
+
266
+ height_on_dir = vectors_product(height_vector, dir_vector)
267
+ vector_length(height_on_dir) / vector_length(dir_vector)
268
+ end
269
+ end
270
+ end