gmath3D 0.2.0 → 0.2.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/VERSION +1 -1
- data/gmath3D.gemspec +6 -3
- data/lib/finite_line.rb +42 -6
- data/lib/gmath3D.rb +3 -0
- data/lib/line.rb +4 -4
- data/lib/matrix_util.rb +55 -0
- data/lib/quat.rb +303 -0
- data/lib/triangle.rb +74 -5
- data/test/test_finite_line.rb +9 -0
- data/test/test_matrix_util.rb +84 -0
- data/test/test_quat.rb +135 -0
- data/test/test_triangle.rb +106 -0
- data/test/test_vector3.rb +2 -0
- metadata +11 -8
- data/test/test_gmath3D.rb +0 -15
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.1
|
data/gmath3D.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{gmath3D}
|
8
|
-
s.version = "0.2.
|
8
|
+
s.version = "0.2.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Toshiyasu Shimizu"]
|
12
|
-
s.date = %q{2011-10-
|
12
|
+
s.date = %q{2011-10-19}
|
13
13
|
s.description = %q{This library defines 3D geometric elements(point, line, plane etc..). It can get two(or more) elements relation, like distance between two elements.}
|
14
14
|
s.email = %q{toshi0328@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -30,7 +30,9 @@ Gem::Specification.new do |s|
|
|
30
30
|
"lib/geom.rb",
|
31
31
|
"lib/gmath3D.rb",
|
32
32
|
"lib/line.rb",
|
33
|
+
"lib/matrix_util.rb",
|
33
34
|
"lib/plane.rb",
|
35
|
+
"lib/quat.rb",
|
34
36
|
"lib/rectangle.rb",
|
35
37
|
"lib/triangle.rb",
|
36
38
|
"lib/util.rb",
|
@@ -39,9 +41,10 @@ Gem::Specification.new do |s|
|
|
39
41
|
"test/test_box.rb",
|
40
42
|
"test/test_finite_line.rb",
|
41
43
|
"test/test_geom.rb",
|
42
|
-
"test/test_gmath3D.rb",
|
43
44
|
"test/test_line.rb",
|
45
|
+
"test/test_matrix_util.rb",
|
44
46
|
"test/test_plane.rb",
|
47
|
+
"test/test_quat.rb",
|
45
48
|
"test/test_rectangle.rb",
|
46
49
|
"test/test_triangle.rb",
|
47
50
|
"test/test_util.rb",
|
data/lib/finite_line.rb
CHANGED
@@ -10,21 +10,33 @@ public
|
|
10
10
|
attr_accessor :end_point
|
11
11
|
|
12
12
|
# [Input]
|
13
|
-
#
|
13
|
+
# _start_point_ and _end_point_ should be Vector3.
|
14
14
|
# [Output]
|
15
15
|
# return new instance as FiniteLine
|
16
|
-
def initialize(
|
17
|
-
Util.check_arg_type(Vector3,
|
18
|
-
Util.check_arg_type(Vector3,
|
16
|
+
def initialize(start_point = Vector3.new(0.0,0.0,0.0), end_point = Vector3.new(1.0,0.0,0.0))
|
17
|
+
Util.check_arg_type(Vector3, start_point)
|
18
|
+
Util.check_arg_type(Vector3, end_point)
|
19
19
|
super()
|
20
|
-
@start_point =
|
21
|
-
@end_point =
|
20
|
+
@start_point = start_point
|
21
|
+
@end_point = end_point
|
22
22
|
end
|
23
23
|
|
24
24
|
def to_s
|
25
25
|
"FiniteLine[from#{start_point.to_element_s}, to#{end_point.to_element_s}]"
|
26
26
|
end
|
27
27
|
|
28
|
+
# [Input]
|
29
|
+
# _rhs_ should be FiniteLine.
|
30
|
+
# [Output]
|
31
|
+
# return true if rhs equals myself.
|
32
|
+
def ==(rhs)
|
33
|
+
return false if rhs == nil
|
34
|
+
Util.check_arg_type(FiniteLine, rhs)
|
35
|
+
return false if( self.start_point != rhs.start_point)
|
36
|
+
return false if( self.end_point != rhs.end_point)
|
37
|
+
return true
|
38
|
+
end
|
39
|
+
|
28
40
|
# [Output]
|
29
41
|
# return direction as vector from start_point to end_point as Vector3
|
30
42
|
def direction
|
@@ -87,6 +99,30 @@ public
|
|
87
99
|
closest_point = points_ary[distance_ary.index(distance)]
|
88
100
|
return distance, closest_point
|
89
101
|
end
|
102
|
+
|
103
|
+
def self.ary_distance_to_line(finite_lines, target_line)
|
104
|
+
Util.check_arg_type(::Array, finite_lines)
|
105
|
+
Util.check_arg_type(Line, target_line)
|
106
|
+
distance_ary = Array.new(0)
|
107
|
+
point_on_target_ary = Array.new(0)
|
108
|
+
point_on_finite_line_ary = Array.new(0)
|
109
|
+
param_on_target_ary = Array.new(0)
|
110
|
+
param_on_finite_line_ary = Array.new(0)
|
111
|
+
finite_lines.each do | item |
|
112
|
+
distance, point_on_myself, point_on_target, parameter_on_myself, parameter_on_tatget = item.distance(target_line)
|
113
|
+
distance_ary.push(distance)
|
114
|
+
point_on_target_ary.push(point_on_target)
|
115
|
+
point_on_finite_line_ary.push(point_on_myself)
|
116
|
+
param_on_target_ary.push(parameter_on_tatget)
|
117
|
+
param_on_finite_line_ary.push(parameter_on_myself)
|
118
|
+
end
|
119
|
+
distance = distance_ary.min
|
120
|
+
point_on_finiteline = point_on_finite_line_ary[distance_ary.index(distance)]
|
121
|
+
point_on_target = point_on_target_ary[distance_ary.index(distance)]
|
122
|
+
param_on_finiteline = param_on_finite_line_ary[distance_ary.index(distance)]
|
123
|
+
param_on_target = param_on_target_ary[distance_ary.index(distance)]
|
124
|
+
return distance, point_on_finiteline, point_on_target, param_on_finiteline, param_on_target
|
125
|
+
end
|
90
126
|
private
|
91
127
|
def distance_to_point(target)
|
92
128
|
# get distance using infinite line
|
data/lib/gmath3D.rb
CHANGED
data/lib/line.rb
CHANGED
@@ -9,6 +9,10 @@ module GMath3D
|
|
9
9
|
attr_accessor :base_point
|
10
10
|
attr_accessor :direction
|
11
11
|
|
12
|
+
def to_s
|
13
|
+
"Line[point#{@base_point.to_element_s}, vector#{@direction.to_element_s}"
|
14
|
+
end
|
15
|
+
|
12
16
|
# [Input]
|
13
17
|
# _point_ and _direction_ should be Vector3.
|
14
18
|
# [Output]
|
@@ -21,10 +25,6 @@ module GMath3D
|
|
21
25
|
@direction = direction
|
22
26
|
end
|
23
27
|
|
24
|
-
def to_s
|
25
|
-
"Line[point#{@base_point.to_element_s}, vector#{@direction.to_element_s}"
|
26
|
-
end
|
27
|
-
|
28
28
|
# [Input]
|
29
29
|
# _parameter_ should be Numeric.
|
30
30
|
# [Output]
|
data/lib/matrix_util.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'gmath3D'
|
2
|
+
require 'matrix'
|
3
|
+
|
4
|
+
|
5
|
+
class Matrix
|
6
|
+
def self.from_axis(axis, angle)
|
7
|
+
Util.check_arg_type(Vector3, axis)
|
8
|
+
Util.check_arg_type(Numeric, angle)
|
9
|
+
|
10
|
+
return Matrix[
|
11
|
+
[axis.x*axis.x*(1 - Math.cos(angle)) + Math.cos(angle),
|
12
|
+
axis.x*axis.y*(1 - Math.cos(angle)) + axis.z*Math.sin(angle),
|
13
|
+
axis.x*axis.z*(1 - Math.cos(angle)) - axis.y*Math.sin(angle)],
|
14
|
+
[axis.x*axis.y*(1 - Math.cos(angle)) - axis.z*Math.sin(angle),
|
15
|
+
axis.y*axis.y*(1 - Math.cos(angle)) + Math.cos(angle),
|
16
|
+
axis.y*axis.z*(1 - Math.cos(angle)) + axis.x*Math.sin(angle)],
|
17
|
+
[axis.x*axis.z*(1 - Math.cos(angle)) + axis.y*Math.sin(angle),
|
18
|
+
axis.y*axis.z*(1 - Math.cos(angle)) - axis.x*Math.sin(angle),
|
19
|
+
axis.z*axis.z*(1 - Math.cos(angle)) + Math.cos(angle)]]
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.from_quat(quat)
|
23
|
+
Util.check_arg_type(Quat, quat)
|
24
|
+
qw = quat.w
|
25
|
+
qx = quat.x
|
26
|
+
qy = quat.y
|
27
|
+
qz = quat.z
|
28
|
+
|
29
|
+
x2 = 2.0 * qx * qx;
|
30
|
+
y2 = 2.0 * qy * qy;
|
31
|
+
z2 = 2.0 * qz * qz;
|
32
|
+
xy = 2.0 * qx * qy;
|
33
|
+
yz = 2.0 * qy * qz;
|
34
|
+
zx = 2.0 * qz * qx;
|
35
|
+
wx = 2.0 * qw * qx;
|
36
|
+
wy = 2.0 * qw * qy;
|
37
|
+
wz = 2.0 * qw * qz;
|
38
|
+
|
39
|
+
return Matrix[
|
40
|
+
[ 1.0 - y2 - z2, xy + wz, zx - wy],
|
41
|
+
[ xy - wz, 1.0 - z2 - x2, yz + wx],
|
42
|
+
[ zx + wy, yz - wx, 1.0 - x2 - y2]]
|
43
|
+
end
|
44
|
+
|
45
|
+
alias_method :multi_inner, :* # hold original multiply processing
|
46
|
+
def multi_new(rhs)
|
47
|
+
if(rhs.kind_of?(Vector3))
|
48
|
+
ans = self.multi_inner(rhs.to_column_vector)
|
49
|
+
return Vector3.new(ans[0,0], ans[1,0], ans[2,0])
|
50
|
+
end
|
51
|
+
multi_inner(rhs)
|
52
|
+
end
|
53
|
+
alias_method :*, :multi_new # overwrite new multiply processing
|
54
|
+
end
|
55
|
+
|
data/lib/quat.rb
ADDED
@@ -0,0 +1,303 @@
|
|
1
|
+
require 'gmath3D'
|
2
|
+
|
3
|
+
module GMath3D
|
4
|
+
#
|
5
|
+
# Quat represents quaternion.
|
6
|
+
#
|
7
|
+
class Quat
|
8
|
+
public
|
9
|
+
attr_accessor :x
|
10
|
+
attr_accessor :y
|
11
|
+
attr_accessor :z
|
12
|
+
attr_accessor :w
|
13
|
+
|
14
|
+
# [Input]
|
15
|
+
# _x_, _y_, _z_, _w_should be Numeric.
|
16
|
+
# [Output]
|
17
|
+
# return new instance of Quat.
|
18
|
+
def initialize(x=0.0,y=0.0,z=0.0,w=0.0)
|
19
|
+
Util.check_arg_type(Numeric, x)
|
20
|
+
Util.check_arg_type(Numeric, y)
|
21
|
+
Util.check_arg_type(Numeric, z)
|
22
|
+
Util.check_arg_type(Numeric, w)
|
23
|
+
super()
|
24
|
+
@x = x
|
25
|
+
@y = y
|
26
|
+
@z = z
|
27
|
+
@w = w
|
28
|
+
end
|
29
|
+
|
30
|
+
# [Input]
|
31
|
+
# _axsi_ should be Vector3 and _angle_ should be Numeric.
|
32
|
+
# [Output]
|
33
|
+
# return new instance of Quat.
|
34
|
+
def self.from_axis(axis, angle)
|
35
|
+
Util.check_arg_type(Vector3, axis)
|
36
|
+
Util.check_arg_type(Numeric, angle)
|
37
|
+
s = Math.sin(0.5*angle)
|
38
|
+
x = s * axis.x
|
39
|
+
y = s * axis.y
|
40
|
+
z = s * axis.z
|
41
|
+
w = Math.cos(0.5*angle)
|
42
|
+
return Quat.new(x,y,z,w)
|
43
|
+
end
|
44
|
+
|
45
|
+
# [Input]
|
46
|
+
# _matrix_ should be Matrix which row and column size are 3.
|
47
|
+
# [Output]
|
48
|
+
# return new instance of Quat.
|
49
|
+
def self.from_matrix(mat)
|
50
|
+
fourWSquaredMinus1 = mat[0,0] + mat[1,1] + mat[2,2]
|
51
|
+
fourXSquaredMinus1 = mat[0,0] - mat[1,1] - mat[2,2]
|
52
|
+
fourYSquaredMinus1 = mat[1,1] - mat[0,0] - mat[2,2]
|
53
|
+
fourZSquaredMinus1 = mat[2,2] - mat[0,0] - mat[1,1]
|
54
|
+
|
55
|
+
biggestIndex = 0
|
56
|
+
fourBiggestSquaredMinus1 = fourWSquaredMinus1
|
57
|
+
if(fourXSquaredMinus1 > fourBiggestSquaredMinus1)
|
58
|
+
fourBiggestSquaredMinus1 = fourXSquaredMinus1
|
59
|
+
biggestIndex = 1
|
60
|
+
end
|
61
|
+
if(fourYSquaredMinus1 > fourBiggestSquaredMinus1)
|
62
|
+
fourBiggestSquaredMinus1 = fourYSquaredMinus1
|
63
|
+
biggestIndex = 2
|
64
|
+
end
|
65
|
+
if(fourZSquaredMinus1 > fourBiggestSquaredMinus1)
|
66
|
+
fourBiggestSquaredMinus1 = fourZSquaredMinus1
|
67
|
+
biggestIndex = 3
|
68
|
+
end
|
69
|
+
|
70
|
+
biggestVal = Math.sqrt(fourBiggestSquaredMinus1 + 1.0) * 0.5
|
71
|
+
multi = 0.25 / biggestVal
|
72
|
+
|
73
|
+
case biggestIndex
|
74
|
+
when 0
|
75
|
+
w = biggestVal
|
76
|
+
x = (mat[1,2] - mat[2,1]) *multi
|
77
|
+
y = (mat[2,0] - mat[0,2]) *multi
|
78
|
+
z = (mat[0,1] - mat[1,0]) *multi
|
79
|
+
when 1
|
80
|
+
x = biggestVal;
|
81
|
+
w = (mat[1,2] - mat[2,1]) *multi
|
82
|
+
y = (mat[0,1] + mat[1,0]) *multi
|
83
|
+
z = (mat[2,0] + mat[0,2]) *multi
|
84
|
+
when 2
|
85
|
+
y = biggestVal;
|
86
|
+
w = (mat[2,0] - mat[0,2]) *multi
|
87
|
+
x = (mat[0,1] + mat[1,0]) *multi
|
88
|
+
z = (mat[1,2] + mat[2,1]) *multi
|
89
|
+
when 3
|
90
|
+
z = biggestVal;
|
91
|
+
w = (mat[0,1] - mat[1,0]) *multi
|
92
|
+
x = (mat[2,0] + mat[0,2]) *multi
|
93
|
+
y = (mat[1,2] + mat[2,1]) *multi
|
94
|
+
end
|
95
|
+
return Quat.new(x,y,z,w)
|
96
|
+
end
|
97
|
+
|
98
|
+
def to_element_s
|
99
|
+
"[#{@x}, #{@y}, #{@z}, #{@w}]"
|
100
|
+
end
|
101
|
+
|
102
|
+
def to_s
|
103
|
+
"Quat" + to_element_s
|
104
|
+
end
|
105
|
+
|
106
|
+
# [Input]
|
107
|
+
# _rhs_ should be Quat.
|
108
|
+
# [Output]
|
109
|
+
# return true if rhs equals myself.
|
110
|
+
def ==(rhs)
|
111
|
+
return false if( !rhs.kind_of?(Quat) )
|
112
|
+
return false if(self.x != rhs.x)
|
113
|
+
return false if(self.y != rhs.y)
|
114
|
+
return false if(self.z != rhs.z)
|
115
|
+
return false if(self.w != rhs.w)
|
116
|
+
true
|
117
|
+
end
|
118
|
+
|
119
|
+
# [Output]
|
120
|
+
# return conjugated Quat.
|
121
|
+
def conjugate
|
122
|
+
return Quat.new( -self.x, -self.y, -self.z, self.w)
|
123
|
+
end
|
124
|
+
|
125
|
+
# [Output]
|
126
|
+
# return normalized result as Quat.
|
127
|
+
def normalize()
|
128
|
+
mag = Math.sqrt(self.x*self.x + self.y*self.y + self.z*self.z)
|
129
|
+
return Quat.new(self.x/mag, self.y/mag, self.z/mag, self.w/mag)
|
130
|
+
end
|
131
|
+
|
132
|
+
# [Input]
|
133
|
+
# _rhs_ should be Quat.
|
134
|
+
# [Output]
|
135
|
+
# return added result as Quat.
|
136
|
+
def +(rhs)
|
137
|
+
Util.check_arg_type(Quat, rhs)
|
138
|
+
t1 = Vector3.new(self.x, self.y, self.z)
|
139
|
+
t2 = Vector3.new(rhs.x, rhs.y, rhs.z)
|
140
|
+
dot = t1.dot(t2)
|
141
|
+
t3 = t2.cross(t1)
|
142
|
+
|
143
|
+
t1 *= rhs.w
|
144
|
+
t2 *= self.w
|
145
|
+
|
146
|
+
tf = t1 + t2 + t3
|
147
|
+
rtn_w = self.w * rhs.w - dot
|
148
|
+
|
149
|
+
return Quat.new(tf.x, tf.y, tf.z, rtn_w).normalize
|
150
|
+
end
|
151
|
+
|
152
|
+
# [Input]
|
153
|
+
# _rsh_ should be Quat.
|
154
|
+
# [Output]
|
155
|
+
# return (outer products) multiplyed result as Quat.
|
156
|
+
def *(rhs)
|
157
|
+
Util.check_arg_type(Quat, rhs)
|
158
|
+
|
159
|
+
pw = self.w; px = self.x; py = self.y; pz = self.z;
|
160
|
+
qw = rhs.w ; qx = rhs.x ; qy = rhs.y ; qz = rhs.z;
|
161
|
+
|
162
|
+
w = pw * qw - px * qx - py * qy - pz * qz
|
163
|
+
x = pw * qx + px * qw + py * qz - pz * qy
|
164
|
+
y = pw * qy - px * qz + py * qw + pz * qx
|
165
|
+
z = pw * qz + px * qy - py * qx + pz * qw
|
166
|
+
return Quat.new( x,y,z,w )
|
167
|
+
end
|
168
|
+
|
169
|
+
=begin
|
170
|
+
# [Input]
|
171
|
+
# _rhs_ should be Vector3.
|
172
|
+
# [Output]
|
173
|
+
# return subtracted result as Vector3.
|
174
|
+
def -(rhs)
|
175
|
+
subtract(rhs)
|
176
|
+
end
|
177
|
+
|
178
|
+
|
179
|
+
# [Input]
|
180
|
+
# _rhs_ should be Numeric.
|
181
|
+
# [Output]
|
182
|
+
# return divided result as Vector3.
|
183
|
+
def /(rhs)
|
184
|
+
divide(rhs)
|
185
|
+
end
|
186
|
+
|
187
|
+
# [Input]
|
188
|
+
# _rhs_ should be Vector3.
|
189
|
+
# [Output]
|
190
|
+
# return inner product as Numeric
|
191
|
+
def dot(rhs)
|
192
|
+
Util.check_arg_type(Vector3, rhs)
|
193
|
+
self.x*rhs.x + self.y*rhs.y + self.z*rhs.z
|
194
|
+
end
|
195
|
+
|
196
|
+
# [Input]
|
197
|
+
# _rhs_ should be Vector3.
|
198
|
+
# [Output]
|
199
|
+
# return cross product as Vector3.
|
200
|
+
def cross(rhs)
|
201
|
+
Util.check_arg_type(Vector3, rhs)
|
202
|
+
Vector3.new(
|
203
|
+
self.y*rhs.z - self.z*rhs.y,
|
204
|
+
self.z*rhs.x - self.x*rhs.z,
|
205
|
+
self.x*rhs.y - self.y*rhs.x)
|
206
|
+
end
|
207
|
+
|
208
|
+
# [Output]
|
209
|
+
# return vector length as Numeric
|
210
|
+
def length
|
211
|
+
Math::sqrt(self.x*self.x + self.y*self.y + self.z*self.z)
|
212
|
+
end
|
213
|
+
|
214
|
+
# [Input]
|
215
|
+
# _rhs_ should be Vector3.
|
216
|
+
# [Output]
|
217
|
+
# return distance between two points as Numeric.
|
218
|
+
def distance(rhs)
|
219
|
+
Util.check_arg_type(Vector3, rhs)
|
220
|
+
Math::sqrt((self.x - rhs.x)*(self.x - rhs.x) + (self.y - rhs.y)*(self.y - rhs.y) + (self.z - rhs.z)*(self.z - rhs.z))
|
221
|
+
end
|
222
|
+
|
223
|
+
# [Input]
|
224
|
+
# _rhs_ should be Vector3.
|
225
|
+
# [Output]
|
226
|
+
# return two vectors angle as Numeric (rad).
|
227
|
+
def angle(rhs)
|
228
|
+
Util.check_arg_type(Vector3, rhs)
|
229
|
+
vec1Length = self.length ;
|
230
|
+
vec2Length = rhs.length ;
|
231
|
+
return 0.0 if(vec1Length*vec2Length < self.tolerance )
|
232
|
+
v = self.dot(rhs)/(vec1Length*vec2Length)
|
233
|
+
Math::acos( v )
|
234
|
+
end
|
235
|
+
|
236
|
+
# [Output]
|
237
|
+
# return normalized vector as Vector3
|
238
|
+
def normalize()
|
239
|
+
self / self.length.to_f
|
240
|
+
end
|
241
|
+
|
242
|
+
# [Input]
|
243
|
+
# _rhs_ should be Vector3
|
244
|
+
# [Output]
|
245
|
+
# return true if myself and rhs is parallel as boolean
|
246
|
+
def parallel?(rhs)
|
247
|
+
Util.check_arg_type(Vector3, rhs)
|
248
|
+
return false if(self.length < self.tolerance or rhs.length < rhs.tolerance)
|
249
|
+
return false if(self.cross(rhs).length > self.tolerance)
|
250
|
+
return true
|
251
|
+
end
|
252
|
+
|
253
|
+
# [Input]
|
254
|
+
# _rhs_ should be Vector3.
|
255
|
+
# [Output]
|
256
|
+
# return true if myself and rhs have same direction as boolean.
|
257
|
+
def same_direction?(rhs)
|
258
|
+
Util.check_arg_type(Vector3, rhs)
|
259
|
+
return false if(!parallel?(rhs))
|
260
|
+
return false if(self.dot(rhs) < self.tolerance)
|
261
|
+
return true
|
262
|
+
end
|
263
|
+
|
264
|
+
# This function projects self vector to rhs vector.
|
265
|
+
# [Input]
|
266
|
+
# _rhs_ should be Vector3.
|
267
|
+
# [Output]
|
268
|
+
# return projected result as Vector3.
|
269
|
+
def project_to(rhs)
|
270
|
+
Util.check_arg_type(Vector3, rhs)
|
271
|
+
return Vector3.new, 0.0 if( rhs.length < rhs.tolerance )
|
272
|
+
parameter = self.dot( rhs ) / ( rhs.x * rhs.x + rhs.y * rhs.y + rhs.z * rhs.z ).to_f
|
273
|
+
return rhs*parameter, parameter
|
274
|
+
end
|
275
|
+
|
276
|
+
# [Output]
|
277
|
+
# return column vector as Matrix
|
278
|
+
def to_column_vector
|
279
|
+
return Matrix.column_vector([x,y,z])
|
280
|
+
end
|
281
|
+
|
282
|
+
private
|
283
|
+
|
284
|
+
def add(rhs)
|
285
|
+
Util.check_arg_type(Vector3, rhs)
|
286
|
+
Vector3.new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z)
|
287
|
+
end
|
288
|
+
def subtract(rhs)
|
289
|
+
Util.check_arg_type(Vector3, rhs)
|
290
|
+
Vector3.new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z)
|
291
|
+
end
|
292
|
+
def multiply(rhs)
|
293
|
+
Util.check_arg_type(::Numeric, rhs)
|
294
|
+
Vector3.new(self.x * rhs, self.y * rhs, self.z * rhs)
|
295
|
+
end
|
296
|
+
def divide(rhs)
|
297
|
+
Util.check_arg_type(::Numeric, rhs)
|
298
|
+
Vector3.new(self.x.to_f / rhs, self.y / rhs.to_f, self.z / rhs.to_f)
|
299
|
+
end
|
300
|
+
=end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
data/lib/triangle.rb
CHANGED
@@ -123,16 +123,24 @@ public
|
|
123
123
|
end
|
124
124
|
|
125
125
|
# [Input]
|
126
|
-
# _target_ shold be Vector3.
|
126
|
+
# _target_ shold be Vector3 or Line or Plane.
|
127
127
|
# [Output]
|
128
|
-
#
|
128
|
+
# [In case _target_ is Vector3]
|
129
|
+
# return "distance, point on triangle" as [Numeric, Vector3].
|
130
|
+
# [In case _target_ is Line]
|
131
|
+
# return "distance, point on tirangle, point on line, parameter on line" as [Numeric, Vector3, Vector3, Numeric].
|
132
|
+
# [In case _target_ is Plane]
|
133
|
+
# return "distance, intersect_line(or closet edge), point_on_triangle, point_on_plane" as [Numeric, Vector3, Vector3, Vector3].
|
129
134
|
def distance(target)
|
130
135
|
# with Point
|
131
136
|
if(target.kind_of?(Vector3))
|
132
137
|
return distance_to_point(target)
|
133
138
|
elsif(target.kind_of?(Line))
|
134
|
-
|
135
|
-
|
139
|
+
#with Line
|
140
|
+
return distance_to_line(target)
|
141
|
+
elsif(target.kind_of?(Plane))
|
142
|
+
#with Plane
|
143
|
+
return distance_to_plane(target)
|
136
144
|
end
|
137
145
|
Util.raise_argurment_error(target)
|
138
146
|
end
|
@@ -164,6 +172,67 @@ private
|
|
164
172
|
finite_lines = self.edges
|
165
173
|
return FiniteLine.ary_distanc_to_point(finite_lines, target_point)
|
166
174
|
end
|
175
|
+
|
176
|
+
def distance_to_line(target_line)
|
177
|
+
plane = Plane.new( vertices[0], self.normal )
|
178
|
+
distance, point_on_plane, parameter_on_line = plane.distance( target_line )
|
179
|
+
if( point_on_plane == nil)
|
180
|
+
# parallel case
|
181
|
+
# check distance to FiniteLines
|
182
|
+
finite_lines = self.edges
|
183
|
+
distance, point_on_edge, point_on_target, param_on_finiteline, param_on_target =
|
184
|
+
FiniteLine.ary_distance_to_line(finite_lines, target_line)
|
185
|
+
return distance, nil, nil, nil
|
186
|
+
end
|
187
|
+
if( self.contains?(point_on_plane) )
|
188
|
+
return distance, point_on_plane, point_on_plane, parameter_on_line
|
189
|
+
end
|
190
|
+
# check distance to FiniteLines
|
191
|
+
finite_lines = self.edges
|
192
|
+
distance, point_on_edge, point_on_target, param_on_finiteline, param_on_target =
|
193
|
+
FiniteLine.ary_distance_to_line(finite_lines, target_line)
|
194
|
+
return distance, point_on_edge, point_on_target, param_on_target
|
195
|
+
end
|
196
|
+
|
197
|
+
def distance_to_plane(target_plane)
|
198
|
+
triangle_plane = Plane.new( vertices[0], self.normal )
|
199
|
+
distance, intersect_line_each_plane = triangle_plane.distance( target_plane )
|
200
|
+
if( intersect_line_each_plane == nil )
|
201
|
+
return distance, nil, nil, nil
|
202
|
+
end
|
203
|
+
|
204
|
+
# check distance from intersection and each edge.
|
205
|
+
distance_zero_count = 0
|
206
|
+
distance_info = Array.new(0)
|
207
|
+
prallel_edge_ary = Array.new(0)
|
208
|
+
self.edges.each do |edge|
|
209
|
+
distance, point_on_edge, point_on_line = edge.distance( intersect_line_each_plane)
|
210
|
+
if point_on_edge != nil && point_on_line != nil
|
211
|
+
distance_info.push([distance, point_on_edge, point_on_line])
|
212
|
+
if distance <= self.tolerance
|
213
|
+
distance_zero_count += 1
|
214
|
+
end
|
215
|
+
else
|
216
|
+
prallel_edge_ary.push( edge )
|
217
|
+
end
|
218
|
+
end
|
219
|
+
distance_info.sort!{|a,b| a[0] <=> b[0]}
|
220
|
+
# distance, intersect_line(or closet edge), point_on_triangle, point_on_plan
|
221
|
+
if (distance_zero_count == 2)
|
222
|
+
point1 = distance_info[0][1]
|
223
|
+
point2 = distance_info[1][1]
|
224
|
+
if point1.distance(point2) > self.tolerance
|
225
|
+
return 0.0, FiniteLine.new(point1, point2), nil, nil
|
226
|
+
end
|
227
|
+
return 0.0, nil, point1, point1
|
228
|
+
elsif (distance_zero_count == 0)
|
229
|
+
distance, closest_point_on_plane = target_plane.distance(distance_info[0][1])
|
230
|
+
if(distance_info[0][1] != distance_info[1][1])
|
231
|
+
return distance, FiniteLine.new(distance_info[0][1], distance_info[1][1]), nil, nil
|
232
|
+
end
|
233
|
+
return distance, nil, distance_info[0][1], closest_point_on_plane
|
234
|
+
end
|
235
|
+
return 0.0, nil, nil, nil
|
236
|
+
end
|
167
237
|
end
|
168
238
|
end
|
169
|
-
|
data/test/test_finite_line.rb
CHANGED
@@ -24,6 +24,15 @@ class FiniteLineTestCase < MiniTest::Unit::TestCase
|
|
24
24
|
assert_equal("FiniteLine[from[1, 0, 2], to[1, -3.5, 2]]", line.to_s)
|
25
25
|
end
|
26
26
|
|
27
|
+
def test_equals
|
28
|
+
assert_equal(FiniteLine.new(Vector3.new(1,2,3), Vector3.new(2,3,4)),
|
29
|
+
FiniteLine.new(Vector3.new(1.0,2.0,3.0), Vector3.new(2.0,3.0,4.0)))
|
30
|
+
|
31
|
+
assert(FiniteLine.new(Vector3.new(1,2,3), Vector3.new(2,3,4)) == FiniteLine.new(Vector3.new(1.0,2.0,3.0), Vector3.new(2.0,3.0,4.0)))
|
32
|
+
assert(FiniteLine.new(Vector3.new(1,2,3), Vector3.new(2,3,3)) != FiniteLine.new(Vector3.new(1.0,2.0,3.0), Vector3.new(2.0,3.0,4.0)))
|
33
|
+
assert(FiniteLine.new(Vector3.new(1,2,3), Vector3.new(2,3,4)) != FiniteLine.new(Vector3.new(2,3,4), Vector3.new(1,2,3)))
|
34
|
+
end
|
35
|
+
|
27
36
|
def test_direction
|
28
37
|
start_point_tmp = Vector3.new(1.0, 0.0, 2.0)
|
29
38
|
end_point_tmp = Vector3.new(1.0, -3.5, 1.0)
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# -*- coding: cp932 -*-
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'helper'
|
4
|
+
|
5
|
+
include GMath3D
|
6
|
+
|
7
|
+
MiniTest::Unit.autorun
|
8
|
+
|
9
|
+
class MatrixTestCase < MiniTest::Unit::TestCase
|
10
|
+
def setup
|
11
|
+
@mat_default = Matrix.zero(3)
|
12
|
+
@mat = Matrix[[1,2,3],[4,5,6],[7,8,9]]
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_initalize
|
16
|
+
@mat_default.each do |cell|
|
17
|
+
assert_equal(0, cell)
|
18
|
+
end
|
19
|
+
|
20
|
+
i = 1
|
21
|
+
@mat.each do |cell|
|
22
|
+
assert_equal(i, cell)
|
23
|
+
i+=1
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_to_s
|
28
|
+
assert_equal("Matrix[[0, 0, 0], [0, 0, 0], [0, 0, 0]]", @mat_default.to_s)
|
29
|
+
assert_equal("Matrix[[1, 2, 3], [4, 5, 6], [7, 8, 9]]", @mat.to_s)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_multiply
|
33
|
+
mat = Matrix[[3,2,1],[-4,2,1],[3,4,1]]
|
34
|
+
vec = Matrix.column_vector([2,3,4])
|
35
|
+
ans = mat*vec
|
36
|
+
|
37
|
+
assert_equal(ans[0,0], 16)
|
38
|
+
assert_equal(ans[1,0], 2 )
|
39
|
+
assert_equal(ans[2,0], 22)
|
40
|
+
|
41
|
+
vec2 = Vector3.new(2,3,4)
|
42
|
+
ans2 = mat*(vec2)
|
43
|
+
assert_equal(Vector3.new(16,2,22), ans2)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_from_axis
|
47
|
+
local_point = Vector3.new(1,0,1)
|
48
|
+
angle = 45*Math::PI/180
|
49
|
+
local_cod_x = Vector3.new(Math.cos(angle), Math.sin(angle),0)
|
50
|
+
x_vec = Vector3.new(1,0,0)
|
51
|
+
diff_angle = x_vec.angle(local_cod_x)
|
52
|
+
axis = x_vec.cross(local_cod_x).normalize()
|
53
|
+
|
54
|
+
rotate_matrix = Matrix.from_axis(axis, diff_angle)
|
55
|
+
rotated_point = rotate_matrix.inv * local_point
|
56
|
+
assert_equal(Vector3.new(Math.sqrt(2)/2, Math.sqrt(2)/2, 1), rotated_point)
|
57
|
+
|
58
|
+
local_point = Vector3.new(1,0,0)
|
59
|
+
local_cod_x = Vector3.new(1,1,1).normalize()
|
60
|
+
diff_angle = x_vec.angle(local_cod_x)
|
61
|
+
axis = x_vec.cross(local_cod_x).normalize()
|
62
|
+
|
63
|
+
assert_equal(Math::PI/2, local_cod_x.angle(axis))
|
64
|
+
rotate_matrix = Matrix.from_axis(axis, diff_angle)
|
65
|
+
rotated_point = rotate_matrix.inv()*local_point
|
66
|
+
|
67
|
+
assert_in_delta(rotated_point.x, rotated_point.y, rotated_point.tolerance)
|
68
|
+
assert_in_delta(rotated_point.x, rotated_point.z, rotated_point.tolerance)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_from_quat
|
72
|
+
axis = Vector3.new(1,2,4).normalize()
|
73
|
+
angle = 46*Math::PI/180
|
74
|
+
quat = Quat.from_axis(axis, angle)
|
75
|
+
mat_expected = Matrix.from_axis(axis, angle)
|
76
|
+
mat_actual = Matrix.from_quat(quat)
|
77
|
+
|
78
|
+
[0,1,2].each do |i|
|
79
|
+
[0,1,2].each do |j|
|
80
|
+
assert_in_delta( mat_expected[i,j], mat_actual[i,j], 1e-8)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/test/test_quat.rb
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
include GMath3D
|
5
|
+
|
6
|
+
MiniTest::Unit.autorun
|
7
|
+
|
8
|
+
class QuatTestCase < MiniTest::Unit::TestCase
|
9
|
+
def setup
|
10
|
+
@quat_default = Quat.new()
|
11
|
+
@quat1 = Quat.new(2.0, 3.0, 4.0, 1.0)
|
12
|
+
@quat2 = Quat.new(6.0, 7.0, 8.0, 5.0)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_initalize
|
16
|
+
assert_equal(0, @quat_default.x)
|
17
|
+
assert_equal(0, @quat_default.y)
|
18
|
+
assert_equal(0, @quat_default.z)
|
19
|
+
assert_equal(0, @quat_default.w)
|
20
|
+
|
21
|
+
assert_equal(2.0, @quat1.x)
|
22
|
+
assert_equal(3.0, @quat1.y)
|
23
|
+
assert_equal(4.0, @quat1.z)
|
24
|
+
assert_equal(1.0, @quat1.w)
|
25
|
+
|
26
|
+
assert_raises ArgumentError do
|
27
|
+
invalidResult = Quat.new( "hoge" )
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_from_axis
|
32
|
+
axis = Vector3.new(1.0, 0.0, 0.0)
|
33
|
+
rad = 30.0*Math::PI / 180
|
34
|
+
rot_quat = Quat.from_axis(axis, rad)
|
35
|
+
assert_equal( Math.cos(rad/2.0), rot_quat.w)
|
36
|
+
assert_equal( Math.sin(rad/2.0), rot_quat.x)
|
37
|
+
assert_equal( 0.0, rot_quat.y)
|
38
|
+
assert_equal( 0.0, rot_quat.z)
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_from_matrix
|
42
|
+
axis = Vector3.new(1,2,4).normalize()
|
43
|
+
angle = 46*Math::PI/180
|
44
|
+
mat = Matrix.from_axis(axis, angle)
|
45
|
+
quat_expected = Quat.from_axis(axis, angle)
|
46
|
+
quat_actual = Quat.from_matrix(mat)
|
47
|
+
assert_equal(quat_expected, quat_actual)
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_to_s
|
51
|
+
assert_equal("Quat[2.0, 3.0, 4.0, 1.0]", @quat1.to_s)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_assign_value
|
55
|
+
assert_equal(2.0, @quat1.x)
|
56
|
+
assert_equal(3.0, @quat1.y)
|
57
|
+
assert_equal(4.0, @quat1.z)
|
58
|
+
assert_equal(1.0, @quat1.w)
|
59
|
+
|
60
|
+
@quat1.x = 2.0
|
61
|
+
@quat1.y *= 2.0
|
62
|
+
@quat1.z -= 3.0
|
63
|
+
@quat1.w /= 2.0
|
64
|
+
|
65
|
+
assert_equal(2.0, @quat1.x)
|
66
|
+
assert_equal(6.0, @quat1.y)
|
67
|
+
assert_equal(1.0, @quat1.z)
|
68
|
+
assert_equal(0.5, @quat1.w)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_equals
|
72
|
+
assert(!(@quat_default == @quat1))
|
73
|
+
assert(@quat_default != @quat1)
|
74
|
+
|
75
|
+
assert(@quat1 == @quat1)
|
76
|
+
|
77
|
+
quat = Quat.new(2,3,4,1)
|
78
|
+
assert(@quat1 == quat)
|
79
|
+
|
80
|
+
#invlid value comparison
|
81
|
+
assert(@quat1 != "string")
|
82
|
+
assert(@quat1 != -4)
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_conjugate
|
86
|
+
quat1_conjugate = @quat1.conjugate()
|
87
|
+
quat2_conjugate = @quat2.conjugate()
|
88
|
+
|
89
|
+
assert_equal(-2.0, quat1_conjugate.x)
|
90
|
+
assert_equal(-3.0, quat1_conjugate.y)
|
91
|
+
assert_equal(-4.0, quat1_conjugate.z)
|
92
|
+
assert_equal( 1.0, quat1_conjugate.w)
|
93
|
+
assert_equal(-6.0, quat2_conjugate.x)
|
94
|
+
assert_equal(-7.0, quat2_conjugate.y)
|
95
|
+
assert_equal(-8.0, quat2_conjugate.z)
|
96
|
+
assert_equal( 5.0, quat2_conjugate.w)
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_add
|
100
|
+
# implemented, but how to validate?
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_add_invalid_value
|
104
|
+
assert_raises ArgumentError do
|
105
|
+
invalidResult = @quat1 + 5
|
106
|
+
end
|
107
|
+
assert_raises ArgumentError do
|
108
|
+
invalidResult = @quat1 + nil
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_multiply
|
113
|
+
multiply = @quat1 * @quat2
|
114
|
+
assert_equal(-60, multiply.w)
|
115
|
+
assert_equal( 12, multiply.x)
|
116
|
+
assert_equal( 30, multiply.y)
|
117
|
+
assert_equal( 24, multiply.z)
|
118
|
+
|
119
|
+
@quat1 *= @quat2
|
120
|
+
assert_equal(-60, @quat1.w)
|
121
|
+
assert_equal( 12, @quat1.x)
|
122
|
+
assert_equal( 30, @quat1.y)
|
123
|
+
assert_equal( 24, @quat1.z)
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_multiply_invalid_value
|
127
|
+
assert_raises ArgumentError do
|
128
|
+
invalidResult = @quat1 * 3
|
129
|
+
end
|
130
|
+
assert_raises ArgumentError do
|
131
|
+
invalidResult = @quat2 * nil
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
data/test/test_triangle.rb
CHANGED
@@ -147,4 +147,110 @@ class TriangleTestCase < MiniTest::Unit::TestCase
|
|
147
147
|
assert_in_delta(0, distance, @triangle_default.tolerance)
|
148
148
|
assert_equal(@triangle_default.center, point_on_triangle)
|
149
149
|
end
|
150
|
+
|
151
|
+
def test_distance_to_line
|
152
|
+
# on inside
|
153
|
+
line = Line.new(Vector3.new(0,3,-1), Vector3.new(0,0,4))
|
154
|
+
distance, point_on_triangle, point_on_line, param_on_line = @triangle.distance(line)
|
155
|
+
assert_equal(0, distance)
|
156
|
+
assert_equal(Vector3.new(0,3,1), point_on_triangle)
|
157
|
+
assert_equal(Vector3.new(0,3,1), point_on_line)
|
158
|
+
assert_in_delta(0.5, param_on_line, line.tolerance)
|
159
|
+
|
160
|
+
# on edge
|
161
|
+
line = Line.new(Vector3.new(1,3,-1), Vector3.new(0,0,4))
|
162
|
+
distance, point_on_triangle, point_on_line, param_on_line = @triangle.distance(line)
|
163
|
+
assert_equal(0, distance)
|
164
|
+
assert_equal(Vector3.new(1,3,2), point_on_triangle)
|
165
|
+
assert_equal(Vector3.new(1,3,2), point_on_line)
|
166
|
+
assert_in_delta(0.75, param_on_line, line.tolerance)
|
167
|
+
|
168
|
+
# on vertex
|
169
|
+
line = Line.new(Vector3.new(-1,3,0), Vector3.new(1,1,2))
|
170
|
+
distance, point_on_triangle, point_on_line, param_on_line = @triangle.distance(line)
|
171
|
+
assert_equal(0, distance)
|
172
|
+
assert_equal(Vector3.new(-1,3,0), point_on_triangle)
|
173
|
+
assert_equal(Vector3.new(-1,3,0), point_on_line)
|
174
|
+
assert_in_delta(0.0, param_on_line, line.tolerance)
|
175
|
+
|
176
|
+
# closest point is out of triangle1
|
177
|
+
line = Line.new(Vector3.new(2,3,0), Vector3.new(0,0,4))
|
178
|
+
distance, point_on_triangle, point_on_line, param_on_line = @triangle.distance(line)
|
179
|
+
assert_equal(1, distance)
|
180
|
+
assert_equal(Vector3.new(1,3,2), point_on_triangle)
|
181
|
+
assert_equal(Vector3.new(2,3,2), point_on_line)
|
182
|
+
assert_in_delta(0.5, param_on_line, line.tolerance)
|
183
|
+
|
184
|
+
# closest point is out of triangle2
|
185
|
+
line = Line.new(Vector3.new(-2,3,-1), Vector3.new(0,0,1))
|
186
|
+
distance, point_on_triangle, point_on_line, param_on_line = @triangle.distance(line)
|
187
|
+
assert_equal(1, distance)
|
188
|
+
assert_equal(Vector3.new(-1,3,0), point_on_triangle)
|
189
|
+
assert_equal(Vector3.new(-2,3,0), point_on_line)
|
190
|
+
assert_in_delta(1, param_on_line, line.tolerance)
|
191
|
+
|
192
|
+
# parallel case
|
193
|
+
line = Line.new(Vector3.new(1,0,4), Vector3.new(0,6,0))
|
194
|
+
distance, point_on_triangle, point_on_line, param_on_line = @triangle.distance(line)
|
195
|
+
assert_equal(2, distance)
|
196
|
+
assert_equal(nil, point_on_triangle)
|
197
|
+
assert_equal(nil, point_on_line)
|
198
|
+
assert_equal(nil, param_on_line)
|
199
|
+
end
|
200
|
+
|
201
|
+
def test_distance_to_plane
|
202
|
+
# intersect case
|
203
|
+
plane = Plane.new(Vector3.new(0,0,1), Vector3.new(1,0,0))
|
204
|
+
distance, intersect_line, point_on_triangle, point_on_plane = @triangle.distance(plane)
|
205
|
+
assert_equal( 0, distance )
|
206
|
+
point1 = Vector3.new(0,2.5,1)
|
207
|
+
point2 = Vector3.new(0,3.5,1)
|
208
|
+
assert( FiniteLine.new(point1, point2) == intersect_line || FiniteLine.new(point2, point1) == intersect_line)
|
209
|
+
assert_equal( nil, point_on_triangle )
|
210
|
+
assert_equal( nil, point_on_plane )
|
211
|
+
|
212
|
+
# contains edge
|
213
|
+
plane = Plane.new(Vector3.new(1,0,1), Vector3.new(-1,0,0))
|
214
|
+
distance, intersect_line, point_on_triangle, point_on_plane = @triangle.distance(plane)
|
215
|
+
assert_equal( 0, distance )
|
216
|
+
point1 = Vector3.new(1,2,2)
|
217
|
+
point2 = Vector3.new(1,4,2)
|
218
|
+
assert( FiniteLine.new(point1, point2) == intersect_line || FiniteLine.new(point2, point1) == intersect_line)
|
219
|
+
assert_equal( nil, point_on_triangle )
|
220
|
+
assert_equal( nil, point_on_plane )
|
221
|
+
|
222
|
+
# contains vertex
|
223
|
+
plane = Plane.new(Vector3.new(-1,0,1), Vector3.new(1,0,0))
|
224
|
+
distance, intersect_line, point_on_triangle, point_on_plane = @triangle.distance(plane)
|
225
|
+
assert_equal( 0, distance )
|
226
|
+
assert_equal( nil, intersect_line)
|
227
|
+
assert_equal( Vector3.new(-1,3,0), point_on_triangle )
|
228
|
+
assert_equal( Vector3.new(-1,3,0), point_on_plane )
|
229
|
+
|
230
|
+
# closeing point is outside of triangle
|
231
|
+
plane = Plane.new(Vector3.new(-2,0,0), Vector3.new(-1,0,0))
|
232
|
+
distance, intersect_line, point_on_triangle, point_on_plane = @triangle.distance(plane)
|
233
|
+
assert_equal( 1, distance )
|
234
|
+
assert_equal( nil, intersect_line)
|
235
|
+
assert_equal( Vector3.new(-1,3,0), point_on_triangle )
|
236
|
+
assert_equal( Vector3.new(-2,3,0), point_on_plane )
|
237
|
+
|
238
|
+
# parallel to plane
|
239
|
+
plane = Plane.new(Vector3.new(0,0,4), Vector3.new(0,0,1))
|
240
|
+
distance, intersect_line, point_on_triangle, point_on_plane = @triangle_default.distance(plane)
|
241
|
+
assert_equal( 4, distance )
|
242
|
+
assert_equal( nil, intersect_line)
|
243
|
+
assert_equal( nil, point_on_triangle )
|
244
|
+
assert_equal( nil, point_on_plane )
|
245
|
+
|
246
|
+
# parallel to edge
|
247
|
+
plane = Plane.new(Vector3.new(3.5,0,3), Vector3.new(-1,0,0))
|
248
|
+
distance, closest_line, point_on_triangle, point_on_plane = @triangle.distance(plane)
|
249
|
+
assert_equal( 2.5, distance )
|
250
|
+
point1 = Vector3.new(1,2,2)
|
251
|
+
point2 = Vector3.new(1,4,2)
|
252
|
+
assert( FiniteLine.new(point1, point2) == closest_line || FiniteLine.new(point2, point1) == closest_line)
|
253
|
+
assert_equal( nil, point_on_triangle )
|
254
|
+
assert_equal( nil, point_on_plane )
|
255
|
+
end
|
150
256
|
end
|
data/test/test_vector3.rb
CHANGED
@@ -72,6 +72,8 @@ class Vector3TestCase < MiniTest::Unit::TestCase
|
|
72
72
|
vector = Vector3.new(1.0 - floatingError2, 2.0 + floatingError2, 3.0)
|
73
73
|
assert(@vector != vector)
|
74
74
|
|
75
|
+
assert_equal(Vector3.new(1,2,3), Vector3.new(1.0,2.0,3.0))
|
76
|
+
|
75
77
|
#invlid value comparison
|
76
78
|
assert(@vector != "string")
|
77
79
|
assert(@vector != -4)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gmath3D
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,12 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-10-
|
12
|
+
date: 2011-10-19 00:00:00.000000000 +09:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
17
|
-
requirement: &
|
17
|
+
requirement: &2156099140 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ~>
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: 1.0.0
|
23
23
|
type: :development
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *2156099140
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: jeweler
|
28
|
-
requirement: &
|
28
|
+
requirement: &2156097640 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ~>
|
@@ -33,7 +33,7 @@ dependencies:
|
|
33
33
|
version: 1.6.4
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *2156097640
|
37
37
|
description: This library defines 3D geometric elements(point, line, plane etc..).
|
38
38
|
It can get two(or more) elements relation, like distance between two elements.
|
39
39
|
email: toshi0328@gmail.com
|
@@ -56,7 +56,9 @@ files:
|
|
56
56
|
- lib/geom.rb
|
57
57
|
- lib/gmath3D.rb
|
58
58
|
- lib/line.rb
|
59
|
+
- lib/matrix_util.rb
|
59
60
|
- lib/plane.rb
|
61
|
+
- lib/quat.rb
|
60
62
|
- lib/rectangle.rb
|
61
63
|
- lib/triangle.rb
|
62
64
|
- lib/util.rb
|
@@ -65,9 +67,10 @@ files:
|
|
65
67
|
- test/test_box.rb
|
66
68
|
- test/test_finite_line.rb
|
67
69
|
- test/test_geom.rb
|
68
|
-
- test/test_gmath3D.rb
|
69
70
|
- test/test_line.rb
|
71
|
+
- test/test_matrix_util.rb
|
70
72
|
- test/test_plane.rb
|
73
|
+
- test/test_quat.rb
|
71
74
|
- test/test_rectangle.rb
|
72
75
|
- test/test_triangle.rb
|
73
76
|
- test/test_util.rb
|
@@ -88,7 +91,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
88
91
|
version: '0'
|
89
92
|
segments:
|
90
93
|
- 0
|
91
|
-
hash:
|
94
|
+
hash: 3561879194129992333
|
92
95
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
96
|
none: false
|
94
97
|
requirements:
|
data/test/test_gmath3D.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
-
|
3
|
-
require 'helper'
|
4
|
-
require 'test_geom'
|
5
|
-
require 'test_util'
|
6
|
-
require 'test_vector3'
|
7
|
-
require 'test_line'
|
8
|
-
require 'test_finite_line'
|
9
|
-
require 'test_plane'
|
10
|
-
require 'test_rectangle'
|
11
|
-
require 'test_triangle'
|
12
|
-
require 'test_box'
|
13
|
-
|
14
|
-
|
15
|
-
|