mageo 0.0.0 → 0.0.1

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.
data/lib/mageo/vector.rb CHANGED
@@ -3,21 +3,20 @@
3
3
  require "matrix"
4
4
 
5
5
  class Vector
6
- #include Math
7
- class ZeroOperation < Exception; end
8
- class SizeError < Exception; end
6
+ #include Math
7
+ class ZeroOperation < Exception; end
8
+ class SizeError < Exception; end
9
9
 
10
- # Get a unit vector.
11
- def unit_vector
12
- len = self.r
13
- raise Vector::ZeroOperation if (len == 0)
14
- self * (1/len)
15
- # Vector3D.new(@x*(1.0/len), @y*(1.0/len), @z*(1.0/len))
16
- end
17
-
18
- def floor
19
- self.class[* self.map {|val| val.floor}.to_a]
20
- end
10
+ # Get a unit vector.
11
+ def unit_vector
12
+ len = self.r
13
+ raise Vector::ZeroOperation if (len == 0)
14
+ self * (1/len)
15
+ # Vector3D.new(@x*(1.0/len), @y*(1.0/len), @z*(1.0/len))
16
+ end
21
17
 
18
+ def floor
19
+ self.class[* self.map {|val| val.floor}.to_a]
20
+ end
22
21
  end
23
22
 
@@ -9,25 +9,25 @@ require "mageo/axes.rb"
9
9
  require "mageo/vector.rb"
10
10
  require "rubygems"
11
11
  gem "malge"
12
- #require "malge.rb"
13
- require "malge/simultaneousequations.rb"
12
+ require "malge.rb"
13
+ #require "malge/simultaneousequations.rb"
14
14
  #require "simultaneousequations.rb"
15
15
 
16
16
  # Open class to add "to_v3d" method.
17
17
  class Array
18
- # Convert Array to Vector3D
19
- def to_v3d
20
- Vector3D[*self]
21
- #要素数チェックは Vector3D.[] 側でやっている。
22
- end
18
+ # Convert Array to Vector3D
19
+ def to_v3d
20
+ Vector3D[*self]
21
+ #要素数チェックは Vector3D.[] 側でやっている。
22
+ end
23
23
  end
24
24
 
25
25
  class Vector
26
- # Return a new instance converted to Vector3D class.
27
- def to_v3d
28
- Vector3D[*self]
29
- #要素数チェックは Vector3D.[] 側でやっている。
30
- end
26
+ # Return a new instance converted to Vector3D class.
27
+ def to_v3d
28
+ Vector3D[*self]
29
+ #要素数チェックは Vector3D.[] 側でやっている。
30
+ end
31
31
  end
32
32
 
33
33
 
@@ -38,209 +38,208 @@ end
38
38
  # If you want to be in an internal coordinate, you can use Math/Vector3DInternal.rb .
39
39
  #
40
40
  # Memo:
41
- # Vector3DInternal との対比として、Vector3DCartesian という名前にすることも考えたが、
42
- # 長くなるし、普通直交座標で考えるよね、と。
41
+ # Vector3DInternal との対比として、Vector3DCartesian という名前にすることも考えたが、
42
+ # 長くなるし、普通直交座標で考えるよね、と。
43
43
  #
44
- # インスタンス生成の時点で要素数をチェックし、要素の追加削除を禁止しているので
45
- # 要素数は常に3であることが保証されている。
44
+ # インスタンス生成の時点で要素数をチェックし、要素の追加削除を禁止しているので
45
+ # 要素数は常に3であることが保証されている。
46
46
  #
47
47
  class Vector3D < Vector
48
48
 
49
- class TypeError < Exception; end
50
- class ZeroOperation < Exception; end
51
- class RangeError < Exception; end
52
-
53
- # Class methods
54
-
55
- def self.[](*args)
56
- raise RangeError, "#{args}" unless args.size == 3
57
- super(*args)
58
- end
59
-
60
- # Get the exterior product.
61
- def self.exterior_product(vec0, vec1)
62
- [vec0, vec1].each_with_index do |vec, index|
63
- unless (vec.class == Vector3D)
64
- raise TypeError, "Vector #{index}, #{vec.inspect}."
65
- end
66
- end
67
-
68
- bX = vec1[0];
69
- bY = vec1[1];
70
- bZ = vec1[2];
71
-
72
- cX = (vec0[1] * bZ - vec0[2] * bY);
73
- cY = (vec0[2] * bX - vec0[0] * bZ);
74
- cZ = (vec0[0] * bY - vec0[1] * bX);
75
-
76
- self[cX, cY, cZ]
77
- end
78
- class << self
79
- alias :cross_product :exterior_product
80
- alias :vector_product :exterior_product
81
- end
82
-
83
- # Get the scalar triple product.
84
- def self.scalar_triple_product(vec0, vec1, vec2)
85
- [vec0, vec1, vec2].each_with_index do |vec, index|
86
- raise TypeError, "#{index}th vector: #{vec.inspect}" unless (vec.class == Vector3D)
87
- end
88
-
89
- vec0.inner_product(vec1.exterior_product(vec2))
90
- end
91
-
92
- # Get the angle with radian between self and other vectors.
93
- def self.angle_radian(vec0, vec1)
94
- [vec0, vec1].each_with_index do |vec, index|
95
- raise TypeError, "#{index}th vector: #{vec.inspect}" unless (vec.class == Vector3D)
96
- raise ZeroOperation, "#{index}th vector: #{vec.inspect}" if (vec.r == 0.0)
97
- end
98
-
99
- Math::acos(vec0.inner_product(vec1) / (vec0.r * vec1.r))
100
- end
101
-
102
- # Get the angle with degree between self and other vectors.
103
- def self.angle_degree(vec0, vec1)
104
- [vec0, vec1].each_with_index do |vec, index|
105
- raise TypeError, "#{index}th vector: #{vec.inspect}" unless (vec.class == Vector3D)
106
- raise ZeroOperation, "#{index}th vector: #{vec.inspect}" if (vec.r == 0.0)
107
- end
108
-
109
- self.angle_radian(vec0, vec1) * (180.0 / Math::PI)
110
- end
111
-
112
- # Instance methods
113
-
114
- def [](index)
115
- raise RangeError, "index: #{index}." if (index < 0 || 2 < index)
116
- super index
117
- end
118
-
119
- def []=(index, val)
120
- raise RangeError, "index: #{index}." if (index < 0 || 2 < index)
121
- super index, val
122
- end
123
-
124
-
125
- # ベクトルが等しいかチェック。
126
- # other として Vector3D クラス以外のインスタンス渡すと Vector3D::TypeError。
127
- # 両者の差分ベクトルの長さが tolerance 以下という判定になる。
128
- def equal_in_delta?(other, tolerance = 0.0)
129
- raise TypeError if (other.class != Vector3D)
130
- return (other - self).r <= tolerance
131
- end
132
-
133
- # Vectorクラスで用意されているメソッドは Vectorクラスインスタンスを返すようになっているので、
134
- # Vector3D クラスインスタンスを返すようにした + メソッド。
135
- def +(vec)
136
- unless (vec.class == Vector3D)
137
- raise TypeError, "#{vec.inspect}."
138
- end
139
- super(vec).to_v3d
140
- end
141
-
142
- # Vectorクラスで用意されているメソッドは Vectorクラスインスタンスを返すようになっているので、
143
- # Vector3D クラスインスタンスを返すようにした - メソッド。
144
- def -(vec)
145
- unless (vec.class == Vector3D)
146
- raise TypeError, "#{vec.inspect}."
147
- end
148
- super(vec).to_v3d
149
- end
150
-
151
- # Vectorクラスで用意されているメソッドは Vectorクラスインスタンスを返すようになっているので、
152
- # Vector3D クラスインスタンスを返すようにした * メソッド。
153
- # Argument 'val' must have :to_f method.
154
- def *(val)
155
- #raise TypeError if (val.class != Float)
156
- raise TypeError unless val.methods.include?(:to_f)
157
- super(val.to_f).to_v3d
158
- end
159
-
160
- # Vectorクラスで用意されているメソッドは Vectorクラスインスタンスを返すようになっているので、
161
- # Vector3D クラスインスタンスを返すようにした clone メソッド。
162
- def clone
163
- super().to_v3d
164
- end
165
-
166
- # Convert to Vector3DInternal. Non-destructive.
167
- def to_v3di(axes)
168
- #pp axes.is_a?(Axes)
169
- raise TypeError unless axes.is_a?(Axes)
170
-
171
- axes = axes.to_a
172
- Vector3DInternal[ *(SimultaneousEquations.cramer(axes.transpose, self)) ]
173
- end
174
-
175
- #Return size, always 3.
176
- def size
177
- return 3
178
- end
179
-
180
- # Get the exterior product.
181
- def exterior_product(vec)
182
- self.class.exterior_product(self, vec)
183
- end
184
- alias :cross_product :exterior_product
185
- alias :vector_product :exterior_product
186
-
187
- def scalar_triple_product(vec0, vec1)
188
- self.class.scalar_triple_product(self, vec0, vec1)
189
- end
190
-
191
- def angle_radian(vec)
192
- self.class.angle_radian(self, vec)
193
- end
194
-
195
- def angle_degree(vec)
196
- self.class.angle_degree(self, vec)
197
- end
198
-
199
- #3次元極座標への変換した Polar3D インスタンスを返す。
200
- def to_p3d
201
- r = self.r
202
- if r == 0.0
203
- theta = 0.0
204
- phi = 0.0
205
- else
206
- theta = Polar2D.minimum_radian(Math::acos(self[2] / r))
207
- phi = Vector[ self[0], self[1] ].to_p2d.theta
208
- end
209
- Polar3D.new(r, theta, phi)
210
- end
211
-
212
- #x, y, z 軸のいずれかで self を回転する。破壊的。
213
- #axis は 0, 1, 2 のいずれかで、それぞれ x, y, z軸を示す。
214
- #radian は回転する角度で、原点から軸の伸びる方向に対して右ねじ方向を正とする。
215
- #すなわち、軸の正の値の位置から原点を見たとき、左回りが正である。
216
- #e.g., y軸中心で回転し、z軸を x軸になるように変換。
217
- # self.rotate_axis!(1, 0.5*PI)
218
- def rotate_axis!(axis, radian)
219
- raise RangeError, "Axis id is #{axis}." if (axis < 0 || 2 < axis)
220
- #axis1, axis2 はそれぞれ、 x軸から見て y軸, z軸。y に対する z, x。z に対する x, y。
221
- axis1 = (axis + 1) % 3
222
- axis2 = (axis + 2) % 3
223
-
224
- tmp = Array.new(3)
225
- tmp[ axis ] = self[ axis ]
226
- tmp[ axis1 ] = Math::cos(radian) * self[ axis1 ] - Math::sin(radian) * self[ axis2 ]
227
- tmp[ axis2 ] = Math::sin(radian) * self[ axis1 ] + Math::cos(radian) * self[ axis2 ]
228
- tmp.to_v3d
229
- self[0] = tmp[0]
230
- self[1] = tmp[1]
231
- self[2] = tmp[2]
232
- end
233
-
234
- #x, y, z 軸のいずれかで self を回転した座標を返す。非破壊的。
235
- #axis は 0, 1, 2 のいずれかで、それぞれ x, y, z軸を示す。
236
- #radian は回転する角度で、原点から軸の伸びる方向に対して右ねじ方向を正とする。
237
- #すなわち、軸の正の値の位置から原点を見たとき、左回りが正である。
238
- #e.g., y軸中心で回転し、z軸を x軸になるように変換。
239
- # self.rotate_axis(1, 0.5*PI)
240
- def rotate_axis(axis, radian)
241
- tmp = Marshal.load(Marshal.dump(self))
242
- tmp.rotate_axis!(axis, radian)
243
- tmp
244
- end
245
-
49
+ class TypeError < Exception; end
50
+ class ZeroOperation < Exception; end
51
+ class RangeError < Exception; end
52
+
53
+ # Class methods
54
+
55
+ def self.[](*args)
56
+ raise RangeError, "#{args}" unless args.size == 3
57
+ super(*args)
58
+ end
59
+
60
+ # Get the exterior product.
61
+ def self.exterior_product(vec0, vec1)
62
+ [vec0, vec1].each_with_index do |vec, index|
63
+ unless (vec.class == Vector3D)
64
+ raise TypeError, "Vector #{index}, #{vec.inspect}."
65
+ end
66
+ end
67
+
68
+ bX = vec1[0];
69
+ bY = vec1[1];
70
+ bZ = vec1[2];
71
+
72
+ cX = (vec0[1] * bZ - vec0[2] * bY);
73
+ cY = (vec0[2] * bX - vec0[0] * bZ);
74
+ cZ = (vec0[0] * bY - vec0[1] * bX);
75
+
76
+ self[cX, cY, cZ]
77
+ end
78
+ class << self
79
+ alias :cross_product :exterior_product
80
+ alias :vector_product :exterior_product
81
+ end
82
+
83
+ # Get the scalar triple product.
84
+ def self.scalar_triple_product(vec0, vec1, vec2)
85
+ [vec0, vec1, vec2].each_with_index do |vec, index|
86
+ raise TypeError, "#{index}th vector: #{vec.inspect}" unless (vec.class == Vector3D)
87
+ end
88
+
89
+ vec0.inner_product(vec1.exterior_product(vec2))
90
+ end
91
+
92
+ # Get the angle with radian between self and other vectors.
93
+ def self.angle_radian(vec0, vec1)
94
+ [vec0, vec1].each_with_index do |vec, index|
95
+ raise TypeError, "#{index}th vector: #{vec.inspect}" unless (vec.class == Vector3D)
96
+ raise ZeroOperation, "#{index}th vector: #{vec.inspect}" if (vec.r == 0.0)
97
+ end
98
+
99
+ Math::acos(vec0.inner_product(vec1) / (vec0.r * vec1.r))
100
+ end
101
+
102
+ # Get the angle with degree between self and other vectors.
103
+ def self.angle_degree(vec0, vec1)
104
+ [vec0, vec1].each_with_index do |vec, index|
105
+ raise TypeError, "#{index}th vector: #{vec.inspect}" unless (vec.class == Vector3D)
106
+ raise ZeroOperation, "#{index}th vector: #{vec.inspect}" if (vec.r == 0.0)
107
+ end
108
+
109
+ self.angle_radian(vec0, vec1) * (180.0 / Math::PI)
110
+ end
111
+
112
+ # Instance methods
113
+
114
+ def [](index)
115
+ raise RangeError, "index: #{index}." if (index < 0 || 2 < index)
116
+ super index
117
+ end
118
+
119
+ def []=(index, val)
120
+ raise RangeError, "index: #{index}." if (index < 0 || 2 < index)
121
+ super index, val
122
+ end
123
+
124
+
125
+ # ベクトルが等しいかチェック。
126
+ # other として Vector3D クラス以外のインスタンス渡すと Vector3D::TypeError。
127
+ # 両者の差分ベクトルの長さが tolerance 以下という判定になる。
128
+ def equal_in_delta?(other, tolerance = 0.0)
129
+ raise TypeError if (other.class != Vector3D)
130
+ return (other - self).r <= tolerance
131
+ end
132
+
133
+ # Vectorクラスで用意されているメソッドは Vectorクラスインスタンスを返すようになっているので、
134
+ # Vector3D クラスインスタンスを返すようにした + メソッド。
135
+ def +(vec)
136
+ unless (vec.class == Vector3D)
137
+ raise TypeError, "#{vec.inspect}."
138
+ end
139
+ super(vec).to_v3d
140
+ end
141
+
142
+ # Vectorクラスで用意されているメソッドは Vectorクラスインスタンスを返すようになっているので、
143
+ # Vector3D クラスインスタンスを返すようにした - メソッド。
144
+ def -(vec)
145
+ unless (vec.class == Vector3D)
146
+ raise TypeError, "#{vec.inspect}."
147
+ end
148
+ super(vec).to_v3d
149
+ end
150
+
151
+ # Vectorクラスで用意されているメソッドは Vectorクラスインスタンスを返すようになっているので、
152
+ # Vector3D クラスインスタンスを返すようにした * メソッド。
153
+ # Argument 'val' must have :to_f method.
154
+ def *(val)
155
+ #raise TypeError if (val.class != Float)
156
+ raise TypeError unless val.methods.include?(:to_f)
157
+ super(val.to_f).to_v3d
158
+ end
159
+
160
+ # Vectorクラスで用意されているメソッドは Vectorクラスインスタンスを返すようになっているので、
161
+ # Vector3D クラスインスタンスを返すようにした clone メソッド。
162
+ def clone
163
+ super().to_v3d
164
+ end
165
+
166
+ # Convert to Vector3DInternal. Non-destructive.
167
+ def to_v3di(axes)
168
+ #pp axes.is_a?(Axes)
169
+ raise TypeError unless axes.is_a?(Axes)
170
+
171
+ axes = axes.to_a
172
+ Vector3DInternal[ *(Malge::SimultaneousEquations.cramer(axes.transpose, self)) ]
173
+ end
174
+
175
+ #Return size, always 3.
176
+ def size
177
+ return 3
178
+ end
179
+
180
+ # Get the exterior product.
181
+ def exterior_product(vec)
182
+ self.class.exterior_product(self, vec)
183
+ end
184
+ alias :cross_product :exterior_product
185
+ alias :vector_product :exterior_product
186
+
187
+ def scalar_triple_product(vec0, vec1)
188
+ self.class.scalar_triple_product(self, vec0, vec1)
189
+ end
190
+
191
+ def angle_radian(vec)
192
+ self.class.angle_radian(self, vec)
193
+ end
194
+
195
+ def angle_degree(vec)
196
+ self.class.angle_degree(self, vec)
197
+ end
198
+
199
+ #3次元極座標への変換した Polar3D インスタンスを返す。
200
+ def to_p3d
201
+ r = self.r
202
+ if r == 0.0
203
+ theta = 0.0
204
+ phi = 0.0
205
+ else
206
+ theta = Polar2D.minimum_radian(Math::acos(self[2] / r))
207
+ phi = Vector[ self[0], self[1] ].to_p2d.theta
208
+ end
209
+ Polar3D.new(r, theta, phi)
210
+ end
211
+
212
+ #x, y, z 軸のいずれかで self を回転する。破壊的。
213
+ #axis は 0, 1, 2 のいずれかで、それぞれ x, y, z軸を示す。
214
+ #radian は回転する角度で、原点から軸の伸びる方向に対して右ねじ方向を正とする。
215
+ #すなわち、軸の正の値の位置から原点を見たとき、左回りが正である。
216
+ #e.g., y軸中心で回転し、z軸を x軸になるように変換。
217
+ # self.rotate_axis!(1, 0.5*PI)
218
+ def rotate_axis!(axis, radian)
219
+ raise RangeError, "Axis id is #{axis}." if (axis < 0 || 2 < axis)
220
+ #axis1, axis2 はそれぞれ、 x軸から見て y軸, z軸。y に対する z, x。z に対する x, y。
221
+ axis1 = (axis + 1) % 3
222
+ axis2 = (axis + 2) % 3
223
+
224
+ tmp = Array.new(3)
225
+ tmp[ axis ] = self[ axis ]
226
+ tmp[ axis1 ] = Math::cos(radian) * self[ axis1 ] - Math::sin(radian) * self[ axis2 ]
227
+ tmp[ axis2 ] = Math::sin(radian) * self[ axis1 ] + Math::cos(radian) * self[ axis2 ]
228
+ tmp.to_v3d
229
+ self[0] = tmp[0]
230
+ self[1] = tmp[1]
231
+ self[2] = tmp[2]
232
+ end
233
+
234
+ #x, y, z 軸のいずれかで self を回転した座標を返す。非破壊的。
235
+ #axis は 0, 1, 2 のいずれかで、それぞれ x, y, z軸を示す。
236
+ #radian は回転する角度で、原点から軸の伸びる方向に対して右ねじ方向を正とする。
237
+ #すなわち、軸の正の値の位置から原点を見たとき、左回りが正である。
238
+ #e.g., y軸中心で回転し、z軸を x軸になるように変換。
239
+ # self.rotate_axis(1, 0.5*PI)
240
+ def rotate_axis(axis, radian)
241
+ tmp = Marshal.load(Marshal.dump(self))
242
+ tmp.rotate_axis!(axis, radian)
243
+ tmp
244
+ end
246
245
  end