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/CHANGES +9 -0
- data/Gemfile +5 -4
- data/VERSION +1 -1
- data/lib/mageo/axes.rb +77 -78
- data/lib/mageo/cylinder.rb +10 -11
- data/lib/mageo/octahedron.rb +48 -49
- data/lib/mageo/polar2d.rb +78 -79
- data/lib/mageo/polar3d.rb +33 -34
- data/lib/mageo/polyhedron.rb +60 -61
- data/lib/mageo/segment.rb +73 -74
- data/lib/mageo/sphere.rb +6 -7
- data/lib/mageo/tetrahedron.rb +26 -27
- data/lib/mageo/triangle.rb +208 -209
- data/lib/mageo/vector.rb +13 -14
- data/lib/mageo/vector3d.rb +212 -213
- data/lib/mageo/vector3dinternal.rb +107 -108
- data/mageo.gemspec +19 -15
- data/test/test_axes.rb +198 -199
- data/test/test_cylinder.rb +8 -9
- data/test/test_octahedron.rb +140 -142
- data/test/test_polar2d.rb +136 -137
- data/test/test_polar3d.rb +61 -63
- data/test/test_polyhedron.rb +3 -3
- data/test/test_segment.rb +71 -72
- data/test/test_sphere.rb +7 -8
- data/test/test_tetrahedron.rb +115 -117
- data/test/test_triangle.rb +244 -245
- data/test/test_vector.rb +53 -54
- data/test/test_vector3d.rb +409 -411
- data/test/test_vector3dinternal.rb +133 -134
- metadata +34 -52
data/lib/mageo/vector.rb
CHANGED
@@ -3,21 +3,20 @@
|
|
3
3
|
require "matrix"
|
4
4
|
|
5
5
|
class Vector
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
#include Math
|
7
|
+
class ZeroOperation < Exception; end
|
8
|
+
class SizeError < Exception; end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
|
data/lib/mageo/vector3d.rb
CHANGED
@@ -9,25 +9,25 @@ require "mageo/axes.rb"
|
|
9
9
|
require "mageo/vector.rb"
|
10
10
|
require "rubygems"
|
11
11
|
gem "malge"
|
12
|
-
|
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
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
#
|
42
|
-
#
|
41
|
+
# Vector3DInternal との対比として、Vector3DCartesian という名前にすることも考えたが、
|
42
|
+
# 長くなるし、普通直交座標で考えるよね、と。
|
43
43
|
#
|
44
|
-
#
|
45
|
-
#
|
44
|
+
# インスタンス生成の時点で要素数をチェックし、要素の追加削除を禁止しているので
|
45
|
+
# 要素数は常に3であることが保証されている。
|
46
46
|
#
|
47
47
|
class Vector3D < Vector
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
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
|