Class: Mageo::Vector3D

Inherits:
Vector
  • Object
show all
Defined in:
lib/mageo/vector3d.rb

Overview

Vector class specialized for vectors in a three-dimensional Cartesian space. This class provide exterior_product method and others, which is not included in native Vector class. This class is constructed under the assumption in the Cartesian coordinate. If you want to be in an internal coordinate, you can use Math/Mageo::Vector3DInternal.rb .

Memo:

Mageo::Vector3DInternal との対比として、Vector3DCartesian という名前にすることも考えたが、
長くなるし、普通直交座標で考えるよね、と。

インスタンス生成の時点で要素数をチェックし、要素の追加削除を禁止しているので
要素数は常に3であることが保証されている。

Direct Known Subclasses

Vector3DInternal

Defined Under Namespace

Classes: RangeError, TypeError, ZeroOperation

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Vector

#floor, #to_p2d, #to_v3d, #unit_vector

Class Method Details

.[](*args) ⇒ Object

Class methods

Raises:



44
45
46
47
# File 'lib/mageo/vector3d.rb', line 44

def self.[](*args)
  raise RangeError, "#{args}" unless args.size == 3
  super(*args)
end

.angle_degree(vec0, vec1) ⇒ Object

Get the angle with degree between self and other vectors.



92
93
94
95
96
97
98
99
# File 'lib/mageo/vector3d.rb', line 92

def self.angle_degree(vec0, vec1)
  [vec0, vec1].each_with_index do |vec, index|
    raise TypeError, "#{index}th vector: #{vec.inspect}" unless (vec.class == Mageo::Vector3D)
    raise ZeroOperation, "#{index}th vector: #{vec.inspect}" if (vec.r == 0.0)
  end

  self.angle_radian(vec0, vec1) * (180.0 / Math::PI)
end

.angle_radian(vec0, vec1) ⇒ Object

Get the angle with radian between self and other vectors.



82
83
84
85
86
87
88
89
# File 'lib/mageo/vector3d.rb', line 82

def self.angle_radian(vec0, vec1)
  [vec0, vec1].each_with_index do |vec, index|
    raise TypeError, "#{index}th vector: #{vec.inspect}" unless (vec.class == Mageo::Vector3D)
    raise ZeroOperation, "#{index}th vector: #{vec.inspect}" if (vec.r == 0.0)
  end

  Math::acos(vec0.inner_product(vec1) / (vec0.r * vec1.r))
end

.cross_productObject

Get the exterior product.



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/mageo/vector3d.rb', line 68

def self.exterior_product(vec0, vec1)
  [vec0, vec1].each_with_index do |vec, index|
    unless (vec.class == Mageo::Vector3D)
      raise TypeError, "Vector #{index}, #{vec.inspect}."
    end
  end

  bX = vec1[0];
  bY = vec1[1];
  bZ = vec1[2];

  cX = (vec0[1] * bZ - vec0[2] * bY);
  cY = (vec0[2] * bX - vec0[0] * bZ);
  cZ = (vec0[0] * bY - vec0[1] * bX);

  self[cX, cY, cZ]
end

.exterior_product(vec0, vec1) ⇒ Object

Get the exterior product.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/mageo/vector3d.rb', line 50

def self.exterior_product(vec0, vec1)
  [vec0, vec1].each_with_index do |vec, index|
    unless (vec.class == Mageo::Vector3D)
      raise TypeError, "Vector #{index}, #{vec.inspect}."
    end
  end

  bX = vec1[0];
  bY = vec1[1];
  bZ = vec1[2];

  cX = (vec0[1] * bZ - vec0[2] * bY);
  cY = (vec0[2] * bX - vec0[0] * bZ);
  cZ = (vec0[0] * bY - vec0[1] * bX);

  self[cX, cY, cZ]
end

.midpoint(vec1, vec2) ⇒ Object



101
102
103
# File 'lib/mageo/vector3d.rb', line 101

def self.midpoint(vec1, vec2)
  (vec1.to_v3d + vec2.to_v3d)/2.0
end

.scalar_triple_product(vec0, vec1, vec2) ⇒ Object

Get the scalar triple product.



73
74
75
76
77
78
79
# File 'lib/mageo/vector3d.rb', line 73

def self.scalar_triple_product(vec0, vec1, vec2)
  [vec0, vec1, vec2].each_with_index do |vec, index|
    raise TypeError, "#{index}th vector: #{vec.inspect}" unless (vec.class == Mageo::Vector3D)
  end

  vec0.inner_product(vec1.exterior_product(vec2))
end

.vector_productObject

Get the exterior product.



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/mageo/vector3d.rb', line 69

def self.exterior_product(vec0, vec1)
  [vec0, vec1].each_with_index do |vec, index|
    unless (vec.class == Mageo::Vector3D)
      raise TypeError, "Vector #{index}, #{vec.inspect}."
    end
  end

  bX = vec1[0];
  bY = vec1[1];
  bZ = vec1[2];

  cX = (vec0[1] * bZ - vec0[2] * bY);
  cY = (vec0[2] * bX - vec0[0] * bZ);
  cZ = (vec0[0] * bY - vec0[1] * bX);

  self[cX, cY, cZ]
end

Instance Method Details

#*(val) ⇒ Object

Vectorクラスで用意されているメソッドは Vectorクラスインスタンスを返すようになっているので、 Mageo::Vector3D クラスインスタンスを返すようにした * メソッド。 Argument ‘val’ must have :to_f method.

Raises:



146
147
148
149
150
# File 'lib/mageo/vector3d.rb', line 146

def *(val)
  #raise TypeError if (val.class != Float)
  raise TypeError unless val.methods.include?(:to_f)
  super(val.to_f).to_v3d
end

#+(vec) ⇒ Object

Vectorクラスで用意されているメソッドは Vectorクラスインスタンスを返すようになっているので、 Mageo::Vector3D クラスインスタンスを返すようにした + メソッド。



127
128
129
130
131
132
# File 'lib/mageo/vector3d.rb', line 127

def +(vec)
  unless (vec.class == Mageo::Vector3D)
    raise TypeError, "#{vec.inspect}."
  end
  super(vec).to_v3d
end

#-(vec) ⇒ Object

Vectorクラスで用意されているメソッドは Vectorクラスインスタンスを返すようになっているので、 Mageo::Vector3D クラスインスタンスを返すようにした - メソッド。



136
137
138
139
140
141
# File 'lib/mageo/vector3d.rb', line 136

def -(vec)
  unless (vec.class == Mageo::Vector3D)
    raise TypeError, "#{vec.inspect}."
  end
  super(vec).to_v3d
end

#[](index) ⇒ Object

Instance methods

Raises:



107
108
109
110
# File 'lib/mageo/vector3d.rb', line 107

def [](index)
  raise RangeError, "index: #{index}." if (index < 0 || 2 < index)
  super index
end

#[]=(index, val) ⇒ Object

Raises:



112
113
114
115
# File 'lib/mageo/vector3d.rb', line 112

def []=(index, val)
  raise RangeError, "index: #{index}." if (index < 0 || 2 < index)
  super index, val
end

#angle_degree(vec) ⇒ Object



193
194
195
# File 'lib/mageo/vector3d.rb', line 193

def angle_degree(vec)
  self.class.angle_degree(self, vec)
end

#angle_radian(vec) ⇒ Object



189
190
191
# File 'lib/mageo/vector3d.rb', line 189

def angle_radian(vec)
  self.class.angle_radian(self, vec)
end

#cloneObject

Vectorクラスで用意されているメソッドは Vectorクラスインスタンスを返すようになっているので、 Mageo::Vector3D クラスインスタンスを返すようにした clone メソッド。



154
155
156
# File 'lib/mageo/vector3d.rb', line 154

def clone
  super().to_v3d
end

#equal_in_delta?(other, tolerance = 0.0) ⇒ Boolean

ベクトルが等しいかチェック。 other として Mageo::Vector3D クラス以外のインスタンス渡すと Vector3D::TypeError。 両者の差分ベクトルの長さが tolerance 以下という判定になる。

Returns:

  • (Boolean)

Raises:



120
121
122
123
# File 'lib/mageo/vector3d.rb', line 120

def equal_in_delta?(other, tolerance = 0.0)
  raise TypeError if (other.class != Mageo::Vector3D)
  return (other - self).r <= tolerance
end

#exterior_product(vec) ⇒ Object Also known as: cross_product, vector_product

Get the exterior product.



179
180
181
# File 'lib/mageo/vector3d.rb', line 179

def exterior_product(vec)
  self.class.exterior_product(self, vec)
end

#internal_coordinates(axes) ⇒ Object

Convert to Mageo::Vector3DInternal. Non-destructive.

Raises:



159
160
161
162
163
164
# File 'lib/mageo/vector3d.rb', line 159

def internal_coordinates(axes)
  raise TypeError unless axes.is_a?(Mageo::Axes)

  axes = axes.to_a
  Mageo::Vector3DInternal[ *(Malge::SimultaneousEquations.cramer(axes.transpose, self)) ]
end

#midpoint(other) ⇒ Object



244
245
246
# File 'lib/mageo/vector3d.rb', line 244

def midpoint(other)
  self.class.midpoint(self, other)
end

#rotate_axis(axis, radian) ⇒ Object

x, y, z 軸のいずれかで self を回転した座標を返す。非破壊的。 axis は 0, 1, 2 のいずれかで、それぞれ x, y, z軸を示す。 radian は回転する角度で、原点から軸の伸びる方向に対して右ねじ方向を正とする。 すなわち、軸の正の値の位置から原点を見たとき、左回りが正である。 e.g., y軸中心で回転し、z軸を x軸になるように変換。 self.rotate_axis(1, 0.5*PI)



238
239
240
241
242
# File 'lib/mageo/vector3d.rb', line 238

def rotate_axis(axis, radian)
  tmp = Marshal.load(Marshal.dump(self))
  tmp.rotate_axis!(axis, radian)
  tmp
end

#rotate_axis!(axis, radian) ⇒ Object

x, y, z 軸のいずれかで self を回転する。破壊的。 axis は 0, 1, 2 のいずれかで、それぞれ x, y, z軸を示す。 radian は回転する角度で、原点から軸の伸びる方向に対して右ねじ方向を正とする。 すなわち、軸の正の値の位置から原点を見たとき、左回りが正である。 e.g., y軸中心で回転し、z軸を x軸になるように変換。 self.rotate_axis!(1, 0.5*PI)

Raises:



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/mageo/vector3d.rb', line 216

def rotate_axis!(axis, radian)
  raise RangeError, "Axis id is #{axis}." if (axis < 0 || 2 < axis)
  #axis1, axis2 はそれぞれ、 x軸から見て y軸, z軸。y に対する z, x。z に対する x, y。
  axis1 = (axis + 1) % 3
  axis2 = (axis + 2) % 3

  tmp = Array.new(3)
  tmp[ axis  ] = self[ axis  ]
  tmp[ axis1 ] = Math::cos(radian) * self[ axis1 ] - Math::sin(radian) * self[ axis2 ]
  tmp[ axis2 ] = Math::sin(radian) * self[ axis1 ] + Math::cos(radian) * self[ axis2 ]
  tmp.to_v3d
  self[0] = tmp[0]
  self[1] = tmp[1]
  self[2] = tmp[2]
end

#scalar_triple_product(vec0, vec1) ⇒ Object



185
186
187
# File 'lib/mageo/vector3d.rb', line 185

def scalar_triple_product(vec0, vec1)
  self.class.scalar_triple_product(self, vec0, vec1)
end

#sizeObject

Return size, always 3.



174
175
176
# File 'lib/mageo/vector3d.rb', line 174

def size
  return 3
end

#to_p3dObject

3次元極座標への変換した Mageo::Polar3D インスタンスを返す。



198
199
200
201
202
203
204
205
206
207
208
# File 'lib/mageo/vector3d.rb', line 198

def to_p3d
  r = self.r
  if r == 0.0
    theta = 0.0
    phi = 0.0
  else
    theta = Mageo::Polar2D.minimum_radian(Math::acos(self[2] / r))
    phi = Vector[ self[0], self[1] ].to_p2d.theta
  end
  Mageo::Polar3D.new(r, theta, phi)
end

#to_v3diObject

Change the self.class to Vector3DInternal, Keeping the values of coordinates.



168
169
170
171
# File 'lib/mageo/vector3d.rb', line 168

def to_v3di
  axes = Mageo::Axes.new( [ [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0] ])
  internal_coordinates(axes)
end