gmath3D 0.2.5 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -5
- data/Gemfile +5 -5
- data/LICENSE.txt +20 -20
- data/README.rdoc +19 -19
- data/Rakefile +45 -45
- data/VERSION +1 -1
- data/gmath3D.gemspec +79 -79
- data/lib/box.rb +146 -145
- data/lib/ellipse.rb +11 -11
- data/lib/ext.rb +82 -82
- data/lib/finite_line.rb +244 -244
- data/lib/geom.rb +20 -20
- data/lib/gmath3D.rb +22 -22
- data/lib/line.rb +122 -122
- data/lib/plane.rb +131 -131
- data/lib/polyline.rb +73 -73
- data/lib/quat.rb +170 -170
- data/lib/rectangle.rb +155 -155
- data/lib/tri_mesh.rb +258 -258
- data/lib/triangle.rb +281 -281
- data/lib/util.rb +36 -36
- data/lib/vector3.rb +231 -227
- data/test/helper.rb +15 -15
- data/test/test_box.rb +172 -167
- data/test/test_ellipse.rb +55 -55
- data/test/test_finite_line.rb +306 -306
- data/test/test_geom.rb +17 -17
- data/test/test_line.rb +146 -146
- data/test/test_matrix_util.rb +84 -84
- data/test/test_plane.rb +200 -200
- data/test/test_polyline.rb +93 -93
- data/test/test_quat.rb +144 -144
- data/test/test_rectangle.rb +184 -184
- data/test/test_tri_mesh.rb +186 -186
- data/test/test_triangle.rb +318 -318
- data/test/test_util.rb +88 -88
- data/test/test_vector3.rb +453 -439
- metadata +8 -8
data/lib/ellipse.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
require 'gmath3D'
|
2
|
-
|
3
|
-
module GMath3D
|
4
|
-
#
|
5
|
-
#
|
6
|
-
class Ellipse < Geom
|
7
|
-
def initialize(origin = Vector3.new(), axis1 = Vector3.new(1,0,0), axis2 = Vector3.new(0,1,0))
|
8
|
-
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
1
|
+
require 'gmath3D'
|
2
|
+
|
3
|
+
module GMath3D
|
4
|
+
#
|
5
|
+
#
|
6
|
+
class Ellipse < Geom
|
7
|
+
def initialize(origin = Vector3.new(), axis1 = Vector3.new(1,0,0), axis2 = Vector3.new(0,1,0))
|
8
|
+
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/lib/ext.rb
CHANGED
@@ -1,82 +1,82 @@
|
|
1
|
-
require 'gmath3D'
|
2
|
-
require 'matrix'
|
3
|
-
|
4
|
-
module GMath3D
|
5
|
-
class ::Matrix
|
6
|
-
def self.from_axis(axis, angle)
|
7
|
-
Util3D::check_arg_type(Vector3, axis)
|
8
|
-
Util3D::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
|
-
Util3D::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
|
-
|
56
|
-
class ::Array
|
57
|
-
def sum
|
58
|
-
s, n = self.sum_with_number
|
59
|
-
return s
|
60
|
-
end
|
61
|
-
def avg
|
62
|
-
s, n = self.sum_with_number
|
63
|
-
return s / n
|
64
|
-
end
|
65
|
-
|
66
|
-
def sum_with_number
|
67
|
-
return nil, 0 if(self.size <= 0)
|
68
|
-
s = nil
|
69
|
-
n = 0
|
70
|
-
self.each do |v|
|
71
|
-
next if v.nil?
|
72
|
-
if(s==nil)
|
73
|
-
s = v
|
74
|
-
else
|
75
|
-
s += v
|
76
|
-
end
|
77
|
-
n += 1
|
78
|
-
end
|
79
|
-
return s, n
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
1
|
+
require 'gmath3D'
|
2
|
+
require 'matrix'
|
3
|
+
|
4
|
+
module GMath3D
|
5
|
+
class ::Matrix
|
6
|
+
def self.from_axis(axis, angle)
|
7
|
+
Util3D::check_arg_type(Vector3, axis)
|
8
|
+
Util3D::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
|
+
Util3D::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
|
+
|
56
|
+
class ::Array
|
57
|
+
def sum
|
58
|
+
s, n = self.sum_with_number
|
59
|
+
return s
|
60
|
+
end
|
61
|
+
def avg
|
62
|
+
s, n = self.sum_with_number
|
63
|
+
return s / n
|
64
|
+
end
|
65
|
+
|
66
|
+
def sum_with_number
|
67
|
+
return nil, 0 if(self.size <= 0)
|
68
|
+
s = nil
|
69
|
+
n = 0
|
70
|
+
self.each do |v|
|
71
|
+
next if v.nil?
|
72
|
+
if(s==nil)
|
73
|
+
s = v
|
74
|
+
else
|
75
|
+
s += v
|
76
|
+
end
|
77
|
+
n += 1
|
78
|
+
end
|
79
|
+
return s, n
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/finite_line.rb
CHANGED
@@ -1,244 +1,244 @@
|
|
1
|
-
require 'gmath3D'
|
2
|
-
|
3
|
-
module GMath3D
|
4
|
-
#
|
5
|
-
# FiniteLine represents a finite line on 3D space.
|
6
|
-
#
|
7
|
-
class FiniteLine < Geom
|
8
|
-
public
|
9
|
-
attr_accessor :start_point
|
10
|
-
attr_accessor :end_point
|
11
|
-
|
12
|
-
include BoxAvailable
|
13
|
-
|
14
|
-
# [Input]
|
15
|
-
# _start_point_ and _end_point_ should be Vector3.
|
16
|
-
# [Output]
|
17
|
-
# return new instance as FiniteLine
|
18
|
-
def initialize(start_point = Vector3.new(0,0,0), end_point = Vector3.new(1,0,0))
|
19
|
-
Util3D.check_arg_type(Vector3, start_point)
|
20
|
-
Util3D.check_arg_type(Vector3, end_point)
|
21
|
-
super()
|
22
|
-
@start_point = start_point
|
23
|
-
@end_point = end_point
|
24
|
-
end
|
25
|
-
|
26
|
-
def initialize_copy( original_obj )
|
27
|
-
@start_point = original_obj.start_point.dup
|
28
|
-
@end_point = original_obj.end_point.dup
|
29
|
-
end
|
30
|
-
|
31
|
-
def to_s
|
32
|
-
"FiniteLine[from#{start_point.to_element_s}, to#{end_point.to_element_s}]"
|
33
|
-
end
|
34
|
-
|
35
|
-
# [Input]
|
36
|
-
# _mat_ should be Matrix which row and col size are 3.
|
37
|
-
# [Output]
|
38
|
-
# return rotated FiniteLine.
|
39
|
-
def rotate(mat)
|
40
|
-
rot_start_point = mat*start_point
|
41
|
-
rot_end_point = mat*end_point
|
42
|
-
return FiniteLine.new(rot_start_point, rot_end_point)
|
43
|
-
end
|
44
|
-
|
45
|
-
# [Input]
|
46
|
-
# _rhs_ should be FiniteLine.
|
47
|
-
# [Output]
|
48
|
-
# return true if rhs equals myself.
|
49
|
-
def ==(rhs)
|
50
|
-
return false if rhs == nil
|
51
|
-
return false if !rhs.kind_of?(FiniteLine)
|
52
|
-
return false if( self.start_point != rhs.start_point)
|
53
|
-
return false if( self.end_point != rhs.end_point)
|
54
|
-
return true
|
55
|
-
end
|
56
|
-
|
57
|
-
# [Output]
|
58
|
-
# return Array of start_point and end_point.
|
59
|
-
def vertices
|
60
|
-
return [start_point, end_point]
|
61
|
-
end
|
62
|
-
|
63
|
-
# [Output]
|
64
|
-
# return direction as vector from start_point to end_point as Vector3
|
65
|
-
def direction
|
66
|
-
@end_point - @start_point
|
67
|
-
end
|
68
|
-
|
69
|
-
# [Input]
|
70
|
-
# _parameter_ should be Numeric.
|
71
|
-
# [Output]
|
72
|
-
# return a point on line at input parameter position as Vector3
|
73
|
-
def point(parameter)
|
74
|
-
if(parameter < 0.0 or 1.0 < parameter)
|
75
|
-
return nil
|
76
|
-
else
|
77
|
-
return @start_point * (1.0 - parameter) + @end_point * parameter
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
# [Output]
|
82
|
-
# return length as Numeric
|
83
|
-
def length
|
84
|
-
@start_point.distance(@end_point)
|
85
|
-
end
|
86
|
-
|
87
|
-
# This function returns closest distance between FiniteLine and anothor element.
|
88
|
-
# [Input]
|
89
|
-
# _target_ should be Vector3 or Line or FiniteLine
|
90
|
-
#
|
91
|
-
# [Output]
|
92
|
-
# [in case _target_ is Vector3]
|
93
|
-
# return "distance, closest point on myself, parameter on myself" as [Numeric, Vector3, Numeric]
|
94
|
-
# [in case _target_ is Line or FiniteLine]
|
95
|
-
# return "distance, point on myself, point on target, parameter on myself, parameter on tatget"
|
96
|
-
# as [Numeric, Vector3, Vector3, Numeric, Numeric]
|
97
|
-
def distance(target)
|
98
|
-
# with Point
|
99
|
-
if(target.kind_of?(Vector3))
|
100
|
-
return distance_to_point(target)
|
101
|
-
#with Line
|
102
|
-
elsif(target.kind_of?(Line))
|
103
|
-
return distance_to_line(target)
|
104
|
-
#widh Finite Line
|
105
|
-
elsif(target.kind_of?(FiniteLine))
|
106
|
-
return distance_to_finite_line(target)
|
107
|
-
end
|
108
|
-
Util3D.raise_argurment_error(target)
|
109
|
-
end
|
110
|
-
|
111
|
-
def self.ary_distanc_to_point(finite_lines, target_point)
|
112
|
-
Util3D.check_arg_type(::Array, finite_lines)
|
113
|
-
Util3D.check_arg_type(Vector3, target_point)
|
114
|
-
distance_ary = Array.new(0)
|
115
|
-
points_ary = Array.new(0)
|
116
|
-
finite_lines.each do | item |
|
117
|
-
distance, point = item.distance(target_point)
|
118
|
-
distance_ary.push(distance);
|
119
|
-
points_ary.push(point)
|
120
|
-
end
|
121
|
-
distance = distance_ary.min
|
122
|
-
closest_point = points_ary[distance_ary.index(distance)]
|
123
|
-
return distance, closest_point
|
124
|
-
end
|
125
|
-
|
126
|
-
def self.ary_distance_to_line(finite_lines, target_line)
|
127
|
-
Util3D.check_arg_type(::Array, finite_lines)
|
128
|
-
Util3D.check_arg_type(Line, target_line)
|
129
|
-
distance_ary = Array.new(0)
|
130
|
-
point_on_target_ary = Array.new(0)
|
131
|
-
point_on_finite_line_ary = Array.new(0)
|
132
|
-
param_on_target_ary = Array.new(0)
|
133
|
-
param_on_finite_line_ary = Array.new(0)
|
134
|
-
finite_lines.each do | item |
|
135
|
-
distance, point_on_myself, point_on_target, parameter_on_myself, parameter_on_tatget = item.distance(target_line)
|
136
|
-
distance_ary.push(distance)
|
137
|
-
point_on_target_ary.push(point_on_target)
|
138
|
-
point_on_finite_line_ary.push(point_on_myself)
|
139
|
-
param_on_target_ary.push(parameter_on_tatget)
|
140
|
-
param_on_finite_line_ary.push(parameter_on_myself)
|
141
|
-
end
|
142
|
-
distance = distance_ary.min
|
143
|
-
point_on_finiteline = point_on_finite_line_ary[distance_ary.index(distance)]
|
144
|
-
point_on_target = point_on_target_ary[distance_ary.index(distance)]
|
145
|
-
param_on_finiteline = param_on_finite_line_ary[distance_ary.index(distance)]
|
146
|
-
param_on_target = param_on_target_ary[distance_ary.index(distance)]
|
147
|
-
return distance, point_on_finiteline, point_on_target, param_on_finiteline, param_on_target
|
148
|
-
end
|
149
|
-
private
|
150
|
-
def distance_to_point(target)
|
151
|
-
# get distance using infinite line
|
152
|
-
infinite_line = Line.new(self.start_point, self.direction)
|
153
|
-
distance, closest_point, parameter = infinite_line.distance(target)
|
154
|
-
if(0.0 <= parameter and parameter <= 1.0)
|
155
|
-
return distance, closest_point, parameter
|
156
|
-
end
|
157
|
-
|
158
|
-
distance_to_start_point = @start_point.distance(target)
|
159
|
-
distance_to_end_point = @end_point.distance(target)
|
160
|
-
if(distance_to_start_point < distance_to_end_point)
|
161
|
-
distance = distance_to_start_point
|
162
|
-
closest_point = @start_point
|
163
|
-
parameter = 0.0
|
164
|
-
else
|
165
|
-
distance = distance_to_end_point
|
166
|
-
closest_point = @end_point
|
167
|
-
parameter = 1.0
|
168
|
-
end
|
169
|
-
return distance, closest_point, parameter
|
170
|
-
end
|
171
|
-
|
172
|
-
def distance_to_line(target_infinite_line)
|
173
|
-
self_infinite_line = Line.new(self.start_point, self.direction)
|
174
|
-
distance, point1, point2, parameter1, parameter2 = self_infinite_line.distance(target_infinite_line)
|
175
|
-
#parallel
|
176
|
-
return distance, nil, nil, nil, nil if( point1 == nil and point2 == nil)
|
177
|
-
#parameter is in range
|
178
|
-
return distance, point1, point2, parameter1, parameter2 if(0 < parameter1 and parameter1 < 1)
|
179
|
-
distance_to_start_point, closest_point_to_start_point, parameter_to_start_point =
|
180
|
-
target_infinite_line.distance(self.start_point)
|
181
|
-
distance_to_end_point, closest_point_to_end_point, parameter_to_end_point =
|
182
|
-
target_infinite_line.distance(self.end_point)
|
183
|
-
if(distance_to_start_point < distance_to_end_point)
|
184
|
-
return distance_to_start_point, self.start_point, closest_point_to_start_point, 0.0, parameter_to_start_point
|
185
|
-
else
|
186
|
-
return distance_to_end_point, self.end_point, closest_point_to_end_point, 1.0, parameter_to_end_point
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
def distance_to_finite_line(target_finite_line)
|
191
|
-
line1 = Line.new(self.start_point, self.direction)
|
192
|
-
line2 = Line.new(target_finite_line.start_point, target_finite_line.direction)
|
193
|
-
distance, point_myself, point_target, parameter_myself, parameter_target = line1.distance( line2 )
|
194
|
-
if(point_myself == nil and point_target == nil)
|
195
|
-
#prallel or including case
|
196
|
-
point_pair = Array.new(4)
|
197
|
-
point_pair[0] = Array.new([self.start_point, target_finite_line.start_point, 0, 0])
|
198
|
-
point_pair[1] = Array.new([self.start_point, target_finite_line.end_point, 0,1])
|
199
|
-
point_pair[2] = Array.new([self.end_point, target_finite_line.start_point, 1,0])
|
200
|
-
point_pair[3] = Array.new([self.end_point, target_finite_line.end_point,1,1])
|
201
|
-
|
202
|
-
distance_ary = Array.new(0)
|
203
|
-
point_pair.each do |points|
|
204
|
-
distance_ary << points[0].distance(points[1])
|
205
|
-
end
|
206
|
-
distance_min = distance_ary.min
|
207
|
-
distance_min_ary = Array.new(0)
|
208
|
-
distance_min_index = nil
|
209
|
-
distance_ary.each do |item|
|
210
|
-
if( item - tolerance < distance_min )
|
211
|
-
distance_min_ary << item
|
212
|
-
distance_min_index = distance_ary.index(item)
|
213
|
-
end
|
214
|
-
end
|
215
|
-
if( distance_min_ary.size == 1)
|
216
|
-
target_point_pair = point_pair[distance_min_index]
|
217
|
-
distance = target_point_pair[0].distance(target_point_pair[1])
|
218
|
-
return distance, target_point_pair[0], target_point_pair[1], target_point_pair[2], target_point_pair[3]
|
219
|
-
else
|
220
|
-
return distance, nil, nil, nil, nil
|
221
|
-
end
|
222
|
-
#out of range
|
223
|
-
elsif( parameter_myself < 0 or 1 < parameter_myself or parameter_target < 0 or 1 < parameter_target )
|
224
|
-
parameter_myself = [1, parameter_myself].min
|
225
|
-
parameter_myself = [0, parameter_myself].max
|
226
|
-
distance1, point_target, paramter_target_tmp = target_finite_line.distance(point_myself)
|
227
|
-
|
228
|
-
parameter_target = [1, parameter_target].min
|
229
|
-
parameter_target = [0, parameter_target].max
|
230
|
-
distance2, point_myself, parameter_myself_tmp = self.distance(point_target)
|
231
|
-
if(distance1 < distance2)
|
232
|
-
parameter_target = paramter_target_tmp
|
233
|
-
else
|
234
|
-
parameter_myself = parameter_myself_tmp
|
235
|
-
end
|
236
|
-
end
|
237
|
-
point_myself = line1.point(parameter_myself);
|
238
|
-
point_target = line2.point(parameter_target);
|
239
|
-
distance = point_myself.distance(point_target)
|
240
|
-
return distance, point_myself, point_target, parameter_myself, parameter_target
|
241
|
-
end
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
1
|
+
require 'gmath3D'
|
2
|
+
|
3
|
+
module GMath3D
|
4
|
+
#
|
5
|
+
# FiniteLine represents a finite line on 3D space.
|
6
|
+
#
|
7
|
+
class FiniteLine < Geom
|
8
|
+
public
|
9
|
+
attr_accessor :start_point
|
10
|
+
attr_accessor :end_point
|
11
|
+
|
12
|
+
include BoxAvailable
|
13
|
+
|
14
|
+
# [Input]
|
15
|
+
# _start_point_ and _end_point_ should be Vector3.
|
16
|
+
# [Output]
|
17
|
+
# return new instance as FiniteLine
|
18
|
+
def initialize(start_point = Vector3.new(0,0,0), end_point = Vector3.new(1,0,0))
|
19
|
+
Util3D.check_arg_type(Vector3, start_point)
|
20
|
+
Util3D.check_arg_type(Vector3, end_point)
|
21
|
+
super()
|
22
|
+
@start_point = start_point
|
23
|
+
@end_point = end_point
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize_copy( original_obj )
|
27
|
+
@start_point = original_obj.start_point.dup
|
28
|
+
@end_point = original_obj.end_point.dup
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
"FiniteLine[from#{start_point.to_element_s}, to#{end_point.to_element_s}]"
|
33
|
+
end
|
34
|
+
|
35
|
+
# [Input]
|
36
|
+
# _mat_ should be Matrix which row and col size are 3.
|
37
|
+
# [Output]
|
38
|
+
# return rotated FiniteLine.
|
39
|
+
def rotate(mat)
|
40
|
+
rot_start_point = mat*start_point
|
41
|
+
rot_end_point = mat*end_point
|
42
|
+
return FiniteLine.new(rot_start_point, rot_end_point)
|
43
|
+
end
|
44
|
+
|
45
|
+
# [Input]
|
46
|
+
# _rhs_ should be FiniteLine.
|
47
|
+
# [Output]
|
48
|
+
# return true if rhs equals myself.
|
49
|
+
def ==(rhs)
|
50
|
+
return false if rhs == nil
|
51
|
+
return false if !rhs.kind_of?(FiniteLine)
|
52
|
+
return false if( self.start_point != rhs.start_point)
|
53
|
+
return false if( self.end_point != rhs.end_point)
|
54
|
+
return true
|
55
|
+
end
|
56
|
+
|
57
|
+
# [Output]
|
58
|
+
# return Array of start_point and end_point.
|
59
|
+
def vertices
|
60
|
+
return [start_point, end_point]
|
61
|
+
end
|
62
|
+
|
63
|
+
# [Output]
|
64
|
+
# return direction as vector from start_point to end_point as Vector3
|
65
|
+
def direction
|
66
|
+
@end_point - @start_point
|
67
|
+
end
|
68
|
+
|
69
|
+
# [Input]
|
70
|
+
# _parameter_ should be Numeric.
|
71
|
+
# [Output]
|
72
|
+
# return a point on line at input parameter position as Vector3
|
73
|
+
def point(parameter)
|
74
|
+
if(parameter < 0.0 or 1.0 < parameter)
|
75
|
+
return nil
|
76
|
+
else
|
77
|
+
return @start_point * (1.0 - parameter) + @end_point * parameter
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# [Output]
|
82
|
+
# return length as Numeric
|
83
|
+
def length
|
84
|
+
@start_point.distance(@end_point)
|
85
|
+
end
|
86
|
+
|
87
|
+
# This function returns closest distance between FiniteLine and anothor element.
|
88
|
+
# [Input]
|
89
|
+
# _target_ should be Vector3 or Line or FiniteLine
|
90
|
+
#
|
91
|
+
# [Output]
|
92
|
+
# [in case _target_ is Vector3]
|
93
|
+
# return "distance, closest point on myself, parameter on myself" as [Numeric, Vector3, Numeric]
|
94
|
+
# [in case _target_ is Line or FiniteLine]
|
95
|
+
# return "distance, point on myself, point on target, parameter on myself, parameter on tatget"
|
96
|
+
# as [Numeric, Vector3, Vector3, Numeric, Numeric]
|
97
|
+
def distance(target)
|
98
|
+
# with Point
|
99
|
+
if(target.kind_of?(Vector3))
|
100
|
+
return distance_to_point(target)
|
101
|
+
#with Line
|
102
|
+
elsif(target.kind_of?(Line))
|
103
|
+
return distance_to_line(target)
|
104
|
+
#widh Finite Line
|
105
|
+
elsif(target.kind_of?(FiniteLine))
|
106
|
+
return distance_to_finite_line(target)
|
107
|
+
end
|
108
|
+
Util3D.raise_argurment_error(target)
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.ary_distanc_to_point(finite_lines, target_point)
|
112
|
+
Util3D.check_arg_type(::Array, finite_lines)
|
113
|
+
Util3D.check_arg_type(Vector3, target_point)
|
114
|
+
distance_ary = Array.new(0)
|
115
|
+
points_ary = Array.new(0)
|
116
|
+
finite_lines.each do | item |
|
117
|
+
distance, point = item.distance(target_point)
|
118
|
+
distance_ary.push(distance);
|
119
|
+
points_ary.push(point)
|
120
|
+
end
|
121
|
+
distance = distance_ary.min
|
122
|
+
closest_point = points_ary[distance_ary.index(distance)]
|
123
|
+
return distance, closest_point
|
124
|
+
end
|
125
|
+
|
126
|
+
def self.ary_distance_to_line(finite_lines, target_line)
|
127
|
+
Util3D.check_arg_type(::Array, finite_lines)
|
128
|
+
Util3D.check_arg_type(Line, target_line)
|
129
|
+
distance_ary = Array.new(0)
|
130
|
+
point_on_target_ary = Array.new(0)
|
131
|
+
point_on_finite_line_ary = Array.new(0)
|
132
|
+
param_on_target_ary = Array.new(0)
|
133
|
+
param_on_finite_line_ary = Array.new(0)
|
134
|
+
finite_lines.each do | item |
|
135
|
+
distance, point_on_myself, point_on_target, parameter_on_myself, parameter_on_tatget = item.distance(target_line)
|
136
|
+
distance_ary.push(distance)
|
137
|
+
point_on_target_ary.push(point_on_target)
|
138
|
+
point_on_finite_line_ary.push(point_on_myself)
|
139
|
+
param_on_target_ary.push(parameter_on_tatget)
|
140
|
+
param_on_finite_line_ary.push(parameter_on_myself)
|
141
|
+
end
|
142
|
+
distance = distance_ary.min
|
143
|
+
point_on_finiteline = point_on_finite_line_ary[distance_ary.index(distance)]
|
144
|
+
point_on_target = point_on_target_ary[distance_ary.index(distance)]
|
145
|
+
param_on_finiteline = param_on_finite_line_ary[distance_ary.index(distance)]
|
146
|
+
param_on_target = param_on_target_ary[distance_ary.index(distance)]
|
147
|
+
return distance, point_on_finiteline, point_on_target, param_on_finiteline, param_on_target
|
148
|
+
end
|
149
|
+
private
|
150
|
+
def distance_to_point(target)
|
151
|
+
# get distance using infinite line
|
152
|
+
infinite_line = Line.new(self.start_point, self.direction)
|
153
|
+
distance, closest_point, parameter = infinite_line.distance(target)
|
154
|
+
if(0.0 <= parameter and parameter <= 1.0)
|
155
|
+
return distance, closest_point, parameter
|
156
|
+
end
|
157
|
+
|
158
|
+
distance_to_start_point = @start_point.distance(target)
|
159
|
+
distance_to_end_point = @end_point.distance(target)
|
160
|
+
if(distance_to_start_point < distance_to_end_point)
|
161
|
+
distance = distance_to_start_point
|
162
|
+
closest_point = @start_point
|
163
|
+
parameter = 0.0
|
164
|
+
else
|
165
|
+
distance = distance_to_end_point
|
166
|
+
closest_point = @end_point
|
167
|
+
parameter = 1.0
|
168
|
+
end
|
169
|
+
return distance, closest_point, parameter
|
170
|
+
end
|
171
|
+
|
172
|
+
def distance_to_line(target_infinite_line)
|
173
|
+
self_infinite_line = Line.new(self.start_point, self.direction)
|
174
|
+
distance, point1, point2, parameter1, parameter2 = self_infinite_line.distance(target_infinite_line)
|
175
|
+
#parallel
|
176
|
+
return distance, nil, nil, nil, nil if( point1 == nil and point2 == nil)
|
177
|
+
#parameter is in range
|
178
|
+
return distance, point1, point2, parameter1, parameter2 if(0 < parameter1 and parameter1 < 1)
|
179
|
+
distance_to_start_point, closest_point_to_start_point, parameter_to_start_point =
|
180
|
+
target_infinite_line.distance(self.start_point)
|
181
|
+
distance_to_end_point, closest_point_to_end_point, parameter_to_end_point =
|
182
|
+
target_infinite_line.distance(self.end_point)
|
183
|
+
if(distance_to_start_point < distance_to_end_point)
|
184
|
+
return distance_to_start_point, self.start_point, closest_point_to_start_point, 0.0, parameter_to_start_point
|
185
|
+
else
|
186
|
+
return distance_to_end_point, self.end_point, closest_point_to_end_point, 1.0, parameter_to_end_point
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def distance_to_finite_line(target_finite_line)
|
191
|
+
line1 = Line.new(self.start_point, self.direction)
|
192
|
+
line2 = Line.new(target_finite_line.start_point, target_finite_line.direction)
|
193
|
+
distance, point_myself, point_target, parameter_myself, parameter_target = line1.distance( line2 )
|
194
|
+
if(point_myself == nil and point_target == nil)
|
195
|
+
#prallel or including case
|
196
|
+
point_pair = Array.new(4)
|
197
|
+
point_pair[0] = Array.new([self.start_point, target_finite_line.start_point, 0, 0])
|
198
|
+
point_pair[1] = Array.new([self.start_point, target_finite_line.end_point, 0,1])
|
199
|
+
point_pair[2] = Array.new([self.end_point, target_finite_line.start_point, 1,0])
|
200
|
+
point_pair[3] = Array.new([self.end_point, target_finite_line.end_point,1,1])
|
201
|
+
|
202
|
+
distance_ary = Array.new(0)
|
203
|
+
point_pair.each do |points|
|
204
|
+
distance_ary << points[0].distance(points[1])
|
205
|
+
end
|
206
|
+
distance_min = distance_ary.min
|
207
|
+
distance_min_ary = Array.new(0)
|
208
|
+
distance_min_index = nil
|
209
|
+
distance_ary.each do |item|
|
210
|
+
if( item - tolerance < distance_min )
|
211
|
+
distance_min_ary << item
|
212
|
+
distance_min_index = distance_ary.index(item)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
if( distance_min_ary.size == 1)
|
216
|
+
target_point_pair = point_pair[distance_min_index]
|
217
|
+
distance = target_point_pair[0].distance(target_point_pair[1])
|
218
|
+
return distance, target_point_pair[0], target_point_pair[1], target_point_pair[2], target_point_pair[3]
|
219
|
+
else
|
220
|
+
return distance, nil, nil, nil, nil
|
221
|
+
end
|
222
|
+
#out of range
|
223
|
+
elsif( parameter_myself < 0 or 1 < parameter_myself or parameter_target < 0 or 1 < parameter_target )
|
224
|
+
parameter_myself = [1, parameter_myself].min
|
225
|
+
parameter_myself = [0, parameter_myself].max
|
226
|
+
distance1, point_target, paramter_target_tmp = target_finite_line.distance(point_myself)
|
227
|
+
|
228
|
+
parameter_target = [1, parameter_target].min
|
229
|
+
parameter_target = [0, parameter_target].max
|
230
|
+
distance2, point_myself, parameter_myself_tmp = self.distance(point_target)
|
231
|
+
if(distance1 < distance2)
|
232
|
+
parameter_target = paramter_target_tmp
|
233
|
+
else
|
234
|
+
parameter_myself = parameter_myself_tmp
|
235
|
+
end
|
236
|
+
end
|
237
|
+
point_myself = line1.point(parameter_myself);
|
238
|
+
point_target = line2.point(parameter_target);
|
239
|
+
distance = point_myself.distance(point_target)
|
240
|
+
return distance, point_myself, point_target, parameter_myself, parameter_target
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|