mageo 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,23 @@
1
+ #! /usr/bin/ruby
2
+
3
+ require "matrix"
4
+
5
+ class Vector
6
+ #include Math
7
+ class ZeroOperation < Exception; end
8
+ class SizeError < Exception; end
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
21
+
22
+ end
23
+
@@ -0,0 +1,246 @@
1
+ #! /usr/bin/ruby
2
+
3
+ # written by Ippei KISHIDA
4
+ #
5
+ require "matrix"
6
+ require "mageo/polar2d.rb"
7
+ require "mageo/polar3d.rb"
8
+ require "mageo/axes.rb"
9
+ require "mageo/vector.rb"
10
+ require "rubygems"
11
+ gem "malge"
12
+ #require "malge.rb"
13
+ require "malge/simultaneousequations.rb"
14
+ #require "simultaneousequations.rb"
15
+
16
+ # Open class to add "to_v3d" method.
17
+ class Array
18
+ # Convert Array to Vector3D
19
+ def to_v3d
20
+ Vector3D[*self]
21
+ #要素数チェックは Vector3D.[] 側でやっている。
22
+ end
23
+ end
24
+
25
+ class Vector
26
+ # Return a new instance converted to Vector3D class.
27
+ def to_v3d
28
+ Vector3D[*self]
29
+ #要素数チェックは Vector3D.[] 側でやっている。
30
+ end
31
+ end
32
+
33
+
34
+ # Vector class specialized for vectors in a three-dimensional Cartesian space.
35
+ # This class provide exterior_product method and others, which is not included
36
+ # in native Vector class.
37
+ # This class is constructed under the assumption in the Cartesian coordinate.
38
+ # If you want to be in an internal coordinate, you can use Math/Vector3DInternal.rb .
39
+ #
40
+ # Memo:
41
+ # Vector3DInternal との対比として、Vector3DCartesian という名前にすることも考えたが、
42
+ # 長くなるし、普通直交座標で考えるよね、と。
43
+ #
44
+ # インスタンス生成の時点で要素数をチェックし、要素の追加削除を禁止しているので
45
+ # 要素数は常に3であることが保証されている。
46
+ #
47
+ class Vector3D < Vector
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
+
246
+ end
@@ -0,0 +1,125 @@
1
+ require 'mageo/vector3d.rb'
2
+
3
+ class Array
4
+ def to_v3di
5
+ Vector3DInternal[ *self ]
6
+ end
7
+ end
8
+
9
+ # 内部座標系( internal coordinate ) でのベクトルを表現するクラス。
10
+ # 直交座標系とは違い、内積・外積などの角度を含む演算が無効。
11
+ # (直交座標と間違えて)内部座標で内積を求めるなど誤った演算を例外で止めるのが目的。
12
+ # 座標軸の情報は自身では持たない。
13
+ # Actually, this class is very similar to Array class, except for +, -, and * methods.
14
+ # Vector, Vector3D との混在計算は例外を発生。
15
+ #
16
+ # 軸の情報は持たない。
17
+ # 軸に関係ない抽象的な内部座標について議論することもありうるし、
18
+ # 軸情報が必要なのは to_v3d メソッドくらいなので。
19
+ class Vector3DInternal < Vector3D
20
+ class RangeError < Exception; end
21
+ class TypeError < Exception; end
22
+
23
+ #要素数3以外では例外 Vector3DInternalSizeError を発生。
24
+ def self.[]( *args )
25
+ raise RangeError unless args.size == 3
26
+ super *args
27
+ end
28
+
29
+ ## Return order of vector. In this class, always three.
30
+ #def size
31
+ # return 3
32
+ #end
33
+
34
+ # Return self.
35
+ def to_v3di
36
+ return self
37
+ end
38
+
39
+ # Convert to Vector3D. Non-destructive.
40
+ def to_v3d( axes )
41
+ result = [ 0.0, 0.0, 0.0 ]
42
+ 3.times do |i|
43
+ 3.times do |j|
44
+ result[i] += ( self[j] * axes[j][i] )
45
+ end
46
+ end
47
+ Vector3D[ *result ]
48
+ end
49
+
50
+ ## Return an array converted from self.
51
+ #def to_a
52
+ # @coords
53
+ #end
54
+
55
+ ## Check the same vector self and other.
56
+ ## Return false if the size of other is not three.
57
+ #def ==( other )
58
+ # return false if other.size != 3
59
+ # 3.times { |i|
60
+ # return false if self[i] != other[i]
61
+ # }
62
+ # return true
63
+ #end
64
+
65
+ #0〜2 以外の要素にアクセスしようとすると例外 Vector3DInternal::RangeError を発生。
66
+ def []( index )
67
+ raise RangeError if ( index < 0 || 2 < index )
68
+ super index
69
+ end
70
+
71
+ #0〜2 以外の要素にアクセスしようとすると例外 Vector3DInternal::RangeError を発生。
72
+ def []=( index, val )
73
+ raise RangeError if ( index < 0 || 2 < index )
74
+ super index, val
75
+ end
76
+
77
+ #ベクトルとしての加算
78
+ def +(vec)
79
+ unless vec.class == Vector3DInternal
80
+ raise TypeError,
81
+ "Argument: #{vec.inspect}, #{vec.class}."
82
+ end
83
+ result = Vector3DInternal[0.0, 0.0, 0.0]
84
+ 3.times do |i|
85
+ result[ i ] = (self[ i ] + vec[ i ])
86
+ end
87
+ result
88
+ end
89
+
90
+ #ベクトルとしての減算
91
+ def -( vec )
92
+ unless vec.class == Vector3DInternal
93
+ raise TypeError,
94
+ "Argument: #{vec.inspect}, #{vec.class}."
95
+ end
96
+ result = Vector3DInternal[0.0, 0.0, 0.0]
97
+ 3.times do |i|
98
+ result[ i ] = (self[ i ] - vec[ i ])
99
+ end
100
+ result
101
+ end
102
+
103
+ #ベクトルとしての乗算
104
+ def *( val )
105
+ result = Vector3DInternal[0.0, 0.0, 0.0]
106
+ 3.times do |i|
107
+ result[ i ] = ( self[ i ] * val )
108
+ end
109
+ result
110
+ end
111
+
112
+ ## each method
113
+ #def each
114
+ # @coords.each { |i|
115
+ # yield( i )
116
+ # }
117
+ #end
118
+
119
+ #private
120
+ ##
121
+ #def initialize( a, b, c )
122
+ # @coords = [ a, b, c ]
123
+ #end
124
+
125
+ end
@@ -0,0 +1,89 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "mageo"
8
+ s.version = "0.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["ippei94da"]
12
+ s.date = "2012-04-04"
13
+ s.description = "MAth GEOmetry library to deal with 2 and 3 dimension space.\n Cartesian and internal coordinate systems can be used.\n This includes besic objects in 3 dimensional space.\n "
14
+ s.email = "ippei94da@gmail.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ "Gemfile",
22
+ "LICENSE.txt",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "lib/mageo.rb",
27
+ "lib/mageo/axes.rb",
28
+ "lib/mageo/cylinder.rb",
29
+ "lib/mageo/octahedron.rb",
30
+ "lib/mageo/polar2d.rb",
31
+ "lib/mageo/polar3d.rb",
32
+ "lib/mageo/polyhedron.rb",
33
+ "lib/mageo/segment.rb",
34
+ "lib/mageo/sphere.rb",
35
+ "lib/mageo/tetrahedron.rb",
36
+ "lib/mageo/triangle.rb",
37
+ "lib/mageo/vector.rb",
38
+ "lib/mageo/vector3d.rb",
39
+ "lib/mageo/vector3dinternal.rb",
40
+ "mageo.gemspec",
41
+ "test/helper.rb",
42
+ "test/test_axes.rb",
43
+ "test/test_cylinder.rb",
44
+ "test/test_octahedron.rb",
45
+ "test/test_polar2d.rb",
46
+ "test/test_polar3d.rb",
47
+ "test/test_polyhedron.rb",
48
+ "test/test_segment.rb",
49
+ "test/test_sphere.rb",
50
+ "test/test_tetrahedron.rb",
51
+ "test/test_triangle.rb",
52
+ "test/test_vector.rb",
53
+ "test/test_vector3d.rb",
54
+ "test/test_vector3dinternal.rb"
55
+ ]
56
+ s.homepage = "http://github.com/ippei94da/mageo"
57
+ s.licenses = ["MIT"]
58
+ s.require_paths = ["lib"]
59
+ s.rubygems_version = "1.8.21"
60
+ s.summary = "MAth GEOmetry library to deal with 2 and 3 dimension space."
61
+
62
+ if s.respond_to? :specification_version then
63
+ s.specification_version = 3
64
+
65
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
66
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
67
+ s.add_development_dependency(%q<bundler>, ["~> 1.1.3"])
68
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
69
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
70
+ s.add_development_dependency(%q<builtinextension>, [">= 0"])
71
+ s.add_development_dependency(%q<malge>, [">= 0.0.1"])
72
+ else
73
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
74
+ s.add_dependency(%q<bundler>, ["~> 1.1.3"])
75
+ s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
76
+ s.add_dependency(%q<simplecov>, [">= 0"])
77
+ s.add_dependency(%q<builtinextension>, [">= 0"])
78
+ s.add_dependency(%q<malge>, [">= 0.0.1"])
79
+ end
80
+ else
81
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
82
+ s.add_dependency(%q<bundler>, ["~> 1.1.3"])
83
+ s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
84
+ s.add_dependency(%q<simplecov>, [">= 0"])
85
+ s.add_dependency(%q<builtinextension>, [">= 0"])
86
+ s.add_dependency(%q<malge>, [">= 0.0.1"])
87
+ end
88
+ end
89
+