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/triangle.rb
CHANGED
@@ -1,281 +1,281 @@
|
|
1
|
-
require 'gmath3D'
|
2
|
-
|
3
|
-
module GMath3D
|
4
|
-
#
|
5
|
-
# Triangle represents a three edged finite plane on 3D space.
|
6
|
-
#
|
7
|
-
class Triangle < Geom
|
8
|
-
public
|
9
|
-
attr_accessor :vertices
|
10
|
-
|
11
|
-
include BoxAvailable
|
12
|
-
|
13
|
-
# [Input]
|
14
|
-
# _vertex1_, _vertex2_, _vertex3_ should be Vector3.
|
15
|
-
# [Output]
|
16
|
-
# return new instance of Triangle.
|
17
|
-
def initialize(vertex1 = Vector3.new(), vertex2 = Vector3.new(1,0,0), vertex3 = Vector3.new(0,1,0))
|
18
|
-
Util3D.check_arg_type(::Vector3, vertex1)
|
19
|
-
Util3D.check_arg_type(::Vector3, vertex2)
|
20
|
-
Util3D.check_arg_type(::Vector3, vertex3)
|
21
|
-
super()
|
22
|
-
@vertices = Array.new([vertex1, vertex2, vertex3])
|
23
|
-
end
|
24
|
-
|
25
|
-
def initialize_copy( original_obj )
|
26
|
-
@vertices = Array.new(original_obj.vertices.size)
|
27
|
-
for i in 0..@vertices.size-1
|
28
|
-
@vertices[i] = original_obj.vertices[i].dup
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
# [Input]
|
33
|
-
# _rhs_ is Line.
|
34
|
-
# [Output]
|
35
|
-
# return true if rhs equals myself.
|
36
|
-
def ==(rhs)
|
37
|
-
return false if rhs == nil
|
38
|
-
return false if( !rhs.kind_of?(Triangle) )
|
39
|
-
return false if(@vertices.size != rhs.vertices.size)
|
40
|
-
for i in 0..@vertices.size-1
|
41
|
-
return false if(@vertices[i] != rhs.vertices[i])
|
42
|
-
end
|
43
|
-
return true
|
44
|
-
end
|
45
|
-
|
46
|
-
def to_s
|
47
|
-
"Triangle[#{@vertices[0].to_element_s}, #{@vertices[1].to_element_s}, #{@vertices[2].to_element_s}]"
|
48
|
-
end
|
49
|
-
|
50
|
-
# [Input]
|
51
|
-
# _parameter_ should be three element Array of Numeric.
|
52
|
-
# [Output]
|
53
|
-
# return point on triangle at parameter position as Vector3.
|
54
|
-
def point( parameter )
|
55
|
-
Util3D.check_arg_type(::Array, parameter )
|
56
|
-
# TODO Argument check
|
57
|
-
return self.vertices[0]*parameter[0] + self.vertices[1]*parameter[1] + self.vertices[2]*parameter[2]
|
58
|
-
end
|
59
|
-
|
60
|
-
# [Output]
|
61
|
-
# return edges as three element Array of Vector3.
|
62
|
-
def edges
|
63
|
-
return_edges = Array.new(3)
|
64
|
-
return_edges[0] = FiniteLine.new(self.vertices[0], self.vertices[1])
|
65
|
-
return_edges[1] = FiniteLine.new(self.vertices[1], self.vertices[2])
|
66
|
-
return_edges[2] = FiniteLine.new(self.vertices[2], self.vertices[0])
|
67
|
-
return return_edges
|
68
|
-
end
|
69
|
-
|
70
|
-
# [Output]
|
71
|
-
# return area as Numeric.
|
72
|
-
def area
|
73
|
-
vec1 = vertices[1] - vertices[0]
|
74
|
-
vec2 = vertices[2] - vertices[0]
|
75
|
-
outer_product = vec1.cross(vec2)
|
76
|
-
return outer_product.length / 2.0
|
77
|
-
end
|
78
|
-
|
79
|
-
# [Output]
|
80
|
-
# return center point as Vector3.
|
81
|
-
def center
|
82
|
-
return vertices.avg
|
83
|
-
end
|
84
|
-
|
85
|
-
# [Output]
|
86
|
-
# return normal vector as Vector3.
|
87
|
-
def normal
|
88
|
-
vec1 = self.vertices[1] - self.vertices[0]
|
89
|
-
vec2 = self.vertices[2] - self.vertices[0]
|
90
|
-
return (vec1.cross(vec2).normalize)
|
91
|
-
end
|
92
|
-
|
93
|
-
# [Input]
|
94
|
-
# _vertex_index_ should be 0..2.
|
95
|
-
# [Output]
|
96
|
-
# return angle as Numeric(radian).
|
97
|
-
def angle( vertex_index )
|
98
|
-
return nil if(vertex_index < 0 || vertex_index > 2)
|
99
|
-
vert1 = self.vertices[vertex_index]
|
100
|
-
vert2 = self.vertices[(vertex_index+1)%3]
|
101
|
-
vert3 = self.vertices[(vertex_index+2)%3]
|
102
|
-
vec1 = vert2 - vert1
|
103
|
-
vec2 = vert3 - vert1
|
104
|
-
vec1.angle(vec2)
|
105
|
-
end
|
106
|
-
|
107
|
-
# [Output]
|
108
|
-
# return normal vector reversed triangle
|
109
|
-
def reverse
|
110
|
-
return Triangle.new(@vertices[0], @vertices[2], @vertices[1])
|
111
|
-
end
|
112
|
-
|
113
|
-
# [Input]
|
114
|
-
# _check_point_ should be Vector3.
|
115
|
-
# [Output]
|
116
|
-
# return barycentric_coordinate on check_point as three element Array of Numeric.
|
117
|
-
def barycentric_coordinate( check_point )
|
118
|
-
Util3D.check_arg_type(::Vector3, check_point)
|
119
|
-
|
120
|
-
v0 = @vertices[0]
|
121
|
-
v1 = @vertices[1]
|
122
|
-
v2 = @vertices[2]
|
123
|
-
|
124
|
-
d1 = v1 - v0
|
125
|
-
d2 = v2 - v1
|
126
|
-
n = d1.cross(d2);
|
127
|
-
if((n.x).abs >= (n.y).abs && (n.x).abs >= (n.z).abs)
|
128
|
-
uu1 = v0.y - v2.y;
|
129
|
-
uu2 = v1.y - v2.y;
|
130
|
-
uu3 = check_point.y - v0.y;
|
131
|
-
uu4 = check_point.y - v2.y;
|
132
|
-
vv1 = v0.z - v2.z;
|
133
|
-
vv2 = v1.z - v2.z;
|
134
|
-
vv3 = check_point.z - v0.z;
|
135
|
-
vv4 = check_point.z - v2.z;
|
136
|
-
elsif((n.y).abs >= (n.z).abs)
|
137
|
-
uu1 = v0.z - v2.z;
|
138
|
-
uu2 = v1.z - v2.z;
|
139
|
-
uu3 = check_point.z - v0.z;
|
140
|
-
uu4 = check_point.z - v2.z;
|
141
|
-
vv1 = v0.x - v2.x;
|
142
|
-
vv2 = v1.x - v2.x;
|
143
|
-
vv3 = check_point.x - v0.x;
|
144
|
-
vv4 = check_point.x - v2.x;
|
145
|
-
else
|
146
|
-
uu1 = v0.x - v2.x;
|
147
|
-
uu2 = v1.x - v2.x;
|
148
|
-
uu3 = check_point.x - v0.x;
|
149
|
-
uu4 = check_point.x - v2.x;
|
150
|
-
vv1 = v0.y - v2.y;
|
151
|
-
vv2 = v1.y - v2.y;
|
152
|
-
vv3 = check_point.y - v0.y;
|
153
|
-
vv4 = check_point.y - v2.y;
|
154
|
-
end
|
155
|
-
|
156
|
-
denom = vv1 * uu2 - vv2* uu1
|
157
|
-
if(denom == 0.0)
|
158
|
-
return nil
|
159
|
-
end
|
160
|
-
b = Array.new(3)
|
161
|
-
oneOverDenom = 1.0 / denom ;
|
162
|
-
b[0] = (vv4*uu2 - vv2*uu4) * oneOverDenom;
|
163
|
-
b[1] = (vv1*uu3 - vv3*uu1) * oneOverDenom;
|
164
|
-
b[2] = 1.0 - b[0] - b[1];
|
165
|
-
return b;
|
166
|
-
end
|
167
|
-
|
168
|
-
# [Input]
|
169
|
-
# _target_ shold be Vector3 or Line or Plane.
|
170
|
-
# [Output]
|
171
|
-
# [In case _target_ is Vector3]
|
172
|
-
# return "distance, point on triangle" as [Numeric, Vector3].
|
173
|
-
# [In case _target_ is Line]
|
174
|
-
# return "distance, point on tirangle, point on line, parameter on line" as [Numeric, Vector3, Vector3, Numeric].
|
175
|
-
# [In case _target_ is Plane]
|
176
|
-
# return "distance, intersect_line(or closet edge), point_on_triangle, point_on_plane" as [Numeric, Vector3, Vector3, Vector3].
|
177
|
-
def distance(target)
|
178
|
-
# with Point
|
179
|
-
if(target.kind_of?(Vector3))
|
180
|
-
return distance_to_point(target)
|
181
|
-
elsif(target.kind_of?(Line))
|
182
|
-
#with Line
|
183
|
-
return distance_to_line(target)
|
184
|
-
elsif(target.kind_of?(Plane))
|
185
|
-
#with Plane
|
186
|
-
return distance_to_plane(target)
|
187
|
-
end
|
188
|
-
Util3D.raise_argurment_error(target)
|
189
|
-
end
|
190
|
-
|
191
|
-
# [Input]
|
192
|
-
# _check_point_ shold be Vector3.
|
193
|
-
# [Output]
|
194
|
-
# return true if triangle contains _check_point_.
|
195
|
-
def contains?( check_point )
|
196
|
-
Util3D.check_arg_type(Vector3, check_point )
|
197
|
-
plane = Plane.new( vertices[0], self.normal)
|
198
|
-
distance, projected_point = plane.distance(check_point)
|
199
|
-
return false if( distance > self.tolerance )
|
200
|
-
g_coord = self.barycentric_coordinate(check_point)
|
201
|
-
g_coord.each do |item|
|
202
|
-
return false if( item < 0 or 1 < item)
|
203
|
-
end
|
204
|
-
return true
|
205
|
-
end
|
206
|
-
|
207
|
-
private
|
208
|
-
def distance_to_point(target_point)
|
209
|
-
plane = Plane.new( vertices[0], self.normal)
|
210
|
-
distance, projected_point = plane.distance(target_point)
|
211
|
-
if( self.contains?(projected_point))
|
212
|
-
return distance, projected_point
|
213
|
-
end
|
214
|
-
#check distance to FiniteLines
|
215
|
-
finite_lines = self.edges
|
216
|
-
return FiniteLine.ary_distanc_to_point(finite_lines, target_point)
|
217
|
-
end
|
218
|
-
|
219
|
-
def distance_to_line(target_line)
|
220
|
-
plane = Plane.new( vertices[0], self.normal )
|
221
|
-
distance, point_on_plane, parameter_on_line = plane.distance( target_line )
|
222
|
-
if( point_on_plane == nil)
|
223
|
-
# parallel case
|
224
|
-
# check distance to FiniteLines
|
225
|
-
finite_lines = self.edges
|
226
|
-
distance, point_on_edge, point_on_target, param_on_finiteline, param_on_target =
|
227
|
-
FiniteLine.ary_distance_to_line(finite_lines, target_line)
|
228
|
-
return distance, nil, nil, nil
|
229
|
-
end
|
230
|
-
if( self.contains?(point_on_plane) )
|
231
|
-
return distance, point_on_plane, point_on_plane, parameter_on_line
|
232
|
-
end
|
233
|
-
# check distance to FiniteLines
|
234
|
-
finite_lines = self.edges
|
235
|
-
distance, point_on_edge, point_on_target, param_on_finiteline, param_on_target =
|
236
|
-
FiniteLine.ary_distance_to_line(finite_lines, target_line)
|
237
|
-
return distance, point_on_edge, point_on_target, param_on_target
|
238
|
-
end
|
239
|
-
|
240
|
-
def distance_to_plane(target_plane)
|
241
|
-
triangle_plane = Plane.new( vertices[0], self.normal )
|
242
|
-
distance, intersect_line_each_plane = triangle_plane.distance( target_plane )
|
243
|
-
if( intersect_line_each_plane == nil )
|
244
|
-
return distance, nil, nil, nil
|
245
|
-
end
|
246
|
-
|
247
|
-
# check distance from intersection and each edge.
|
248
|
-
distance_zero_count = 0
|
249
|
-
distance_info = Array.new(0)
|
250
|
-
prallel_edge_ary = Array.new(0)
|
251
|
-
self.edges.each do |edge|
|
252
|
-
distance, point_on_edge, point_on_line = edge.distance( intersect_line_each_plane)
|
253
|
-
if point_on_edge != nil && point_on_line != nil
|
254
|
-
distance_info.push([distance, point_on_edge, point_on_line])
|
255
|
-
if distance <= self.tolerance
|
256
|
-
distance_zero_count += 1
|
257
|
-
end
|
258
|
-
else
|
259
|
-
prallel_edge_ary.push( edge )
|
260
|
-
end
|
261
|
-
end
|
262
|
-
distance_info.sort!{|a,b| a[0] <=> b[0]}
|
263
|
-
# distance, intersect_line(or closet edge), point_on_triangle, point_on_plan
|
264
|
-
if (distance_zero_count == 2)
|
265
|
-
point1 = distance_info[0][1]
|
266
|
-
point2 = distance_info[1][1]
|
267
|
-
if point1.distance(point2) > self.tolerance
|
268
|
-
return 0.0, FiniteLine.new(point1, point2), nil, nil
|
269
|
-
end
|
270
|
-
return 0.0, nil, point1, point1
|
271
|
-
elsif (distance_zero_count == 0)
|
272
|
-
distance, closest_point_on_plane = target_plane.distance(distance_info[0][1])
|
273
|
-
if(distance_info[0][1] != distance_info[1][1])
|
274
|
-
return distance, FiniteLine.new(distance_info[0][1], distance_info[1][1]), nil, nil
|
275
|
-
end
|
276
|
-
return distance, nil, distance_info[0][1], closest_point_on_plane
|
277
|
-
end
|
278
|
-
return 0.0, nil, nil, nil
|
279
|
-
end
|
280
|
-
end
|
281
|
-
end
|
1
|
+
require 'gmath3D'
|
2
|
+
|
3
|
+
module GMath3D
|
4
|
+
#
|
5
|
+
# Triangle represents a three edged finite plane on 3D space.
|
6
|
+
#
|
7
|
+
class Triangle < Geom
|
8
|
+
public
|
9
|
+
attr_accessor :vertices
|
10
|
+
|
11
|
+
include BoxAvailable
|
12
|
+
|
13
|
+
# [Input]
|
14
|
+
# _vertex1_, _vertex2_, _vertex3_ should be Vector3.
|
15
|
+
# [Output]
|
16
|
+
# return new instance of Triangle.
|
17
|
+
def initialize(vertex1 = Vector3.new(), vertex2 = Vector3.new(1,0,0), vertex3 = Vector3.new(0,1,0))
|
18
|
+
Util3D.check_arg_type(::Vector3, vertex1)
|
19
|
+
Util3D.check_arg_type(::Vector3, vertex2)
|
20
|
+
Util3D.check_arg_type(::Vector3, vertex3)
|
21
|
+
super()
|
22
|
+
@vertices = Array.new([vertex1, vertex2, vertex3])
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize_copy( original_obj )
|
26
|
+
@vertices = Array.new(original_obj.vertices.size)
|
27
|
+
for i in 0..@vertices.size-1
|
28
|
+
@vertices[i] = original_obj.vertices[i].dup
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# [Input]
|
33
|
+
# _rhs_ is Line.
|
34
|
+
# [Output]
|
35
|
+
# return true if rhs equals myself.
|
36
|
+
def ==(rhs)
|
37
|
+
return false if rhs == nil
|
38
|
+
return false if( !rhs.kind_of?(Triangle) )
|
39
|
+
return false if(@vertices.size != rhs.vertices.size)
|
40
|
+
for i in 0..@vertices.size-1
|
41
|
+
return false if(@vertices[i] != rhs.vertices[i])
|
42
|
+
end
|
43
|
+
return true
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_s
|
47
|
+
"Triangle[#{@vertices[0].to_element_s}, #{@vertices[1].to_element_s}, #{@vertices[2].to_element_s}]"
|
48
|
+
end
|
49
|
+
|
50
|
+
# [Input]
|
51
|
+
# _parameter_ should be three element Array of Numeric.
|
52
|
+
# [Output]
|
53
|
+
# return point on triangle at parameter position as Vector3.
|
54
|
+
def point( parameter )
|
55
|
+
Util3D.check_arg_type(::Array, parameter )
|
56
|
+
# TODO Argument check
|
57
|
+
return self.vertices[0]*parameter[0] + self.vertices[1]*parameter[1] + self.vertices[2]*parameter[2]
|
58
|
+
end
|
59
|
+
|
60
|
+
# [Output]
|
61
|
+
# return edges as three element Array of Vector3.
|
62
|
+
def edges
|
63
|
+
return_edges = Array.new(3)
|
64
|
+
return_edges[0] = FiniteLine.new(self.vertices[0], self.vertices[1])
|
65
|
+
return_edges[1] = FiniteLine.new(self.vertices[1], self.vertices[2])
|
66
|
+
return_edges[2] = FiniteLine.new(self.vertices[2], self.vertices[0])
|
67
|
+
return return_edges
|
68
|
+
end
|
69
|
+
|
70
|
+
# [Output]
|
71
|
+
# return area as Numeric.
|
72
|
+
def area
|
73
|
+
vec1 = vertices[1] - vertices[0]
|
74
|
+
vec2 = vertices[2] - vertices[0]
|
75
|
+
outer_product = vec1.cross(vec2)
|
76
|
+
return outer_product.length / 2.0
|
77
|
+
end
|
78
|
+
|
79
|
+
# [Output]
|
80
|
+
# return center point as Vector3.
|
81
|
+
def center
|
82
|
+
return vertices.avg
|
83
|
+
end
|
84
|
+
|
85
|
+
# [Output]
|
86
|
+
# return normal vector as Vector3.
|
87
|
+
def normal
|
88
|
+
vec1 = self.vertices[1] - self.vertices[0]
|
89
|
+
vec2 = self.vertices[2] - self.vertices[0]
|
90
|
+
return (vec1.cross(vec2).normalize)
|
91
|
+
end
|
92
|
+
|
93
|
+
# [Input]
|
94
|
+
# _vertex_index_ should be 0..2.
|
95
|
+
# [Output]
|
96
|
+
# return angle as Numeric(radian).
|
97
|
+
def angle( vertex_index )
|
98
|
+
return nil if(vertex_index < 0 || vertex_index > 2)
|
99
|
+
vert1 = self.vertices[vertex_index]
|
100
|
+
vert2 = self.vertices[(vertex_index+1)%3]
|
101
|
+
vert3 = self.vertices[(vertex_index+2)%3]
|
102
|
+
vec1 = vert2 - vert1
|
103
|
+
vec2 = vert3 - vert1
|
104
|
+
vec1.angle(vec2)
|
105
|
+
end
|
106
|
+
|
107
|
+
# [Output]
|
108
|
+
# return normal vector reversed triangle
|
109
|
+
def reverse
|
110
|
+
return Triangle.new(@vertices[0], @vertices[2], @vertices[1])
|
111
|
+
end
|
112
|
+
|
113
|
+
# [Input]
|
114
|
+
# _check_point_ should be Vector3.
|
115
|
+
# [Output]
|
116
|
+
# return barycentric_coordinate on check_point as three element Array of Numeric.
|
117
|
+
def barycentric_coordinate( check_point )
|
118
|
+
Util3D.check_arg_type(::Vector3, check_point)
|
119
|
+
|
120
|
+
v0 = @vertices[0]
|
121
|
+
v1 = @vertices[1]
|
122
|
+
v2 = @vertices[2]
|
123
|
+
|
124
|
+
d1 = v1 - v0
|
125
|
+
d2 = v2 - v1
|
126
|
+
n = d1.cross(d2);
|
127
|
+
if((n.x).abs >= (n.y).abs && (n.x).abs >= (n.z).abs)
|
128
|
+
uu1 = v0.y - v2.y;
|
129
|
+
uu2 = v1.y - v2.y;
|
130
|
+
uu3 = check_point.y - v0.y;
|
131
|
+
uu4 = check_point.y - v2.y;
|
132
|
+
vv1 = v0.z - v2.z;
|
133
|
+
vv2 = v1.z - v2.z;
|
134
|
+
vv3 = check_point.z - v0.z;
|
135
|
+
vv4 = check_point.z - v2.z;
|
136
|
+
elsif((n.y).abs >= (n.z).abs)
|
137
|
+
uu1 = v0.z - v2.z;
|
138
|
+
uu2 = v1.z - v2.z;
|
139
|
+
uu3 = check_point.z - v0.z;
|
140
|
+
uu4 = check_point.z - v2.z;
|
141
|
+
vv1 = v0.x - v2.x;
|
142
|
+
vv2 = v1.x - v2.x;
|
143
|
+
vv3 = check_point.x - v0.x;
|
144
|
+
vv4 = check_point.x - v2.x;
|
145
|
+
else
|
146
|
+
uu1 = v0.x - v2.x;
|
147
|
+
uu2 = v1.x - v2.x;
|
148
|
+
uu3 = check_point.x - v0.x;
|
149
|
+
uu4 = check_point.x - v2.x;
|
150
|
+
vv1 = v0.y - v2.y;
|
151
|
+
vv2 = v1.y - v2.y;
|
152
|
+
vv3 = check_point.y - v0.y;
|
153
|
+
vv4 = check_point.y - v2.y;
|
154
|
+
end
|
155
|
+
|
156
|
+
denom = vv1 * uu2 - vv2* uu1
|
157
|
+
if(denom == 0.0)
|
158
|
+
return nil
|
159
|
+
end
|
160
|
+
b = Array.new(3)
|
161
|
+
oneOverDenom = 1.0 / denom ;
|
162
|
+
b[0] = (vv4*uu2 - vv2*uu4) * oneOverDenom;
|
163
|
+
b[1] = (vv1*uu3 - vv3*uu1) * oneOverDenom;
|
164
|
+
b[2] = 1.0 - b[0] - b[1];
|
165
|
+
return b;
|
166
|
+
end
|
167
|
+
|
168
|
+
# [Input]
|
169
|
+
# _target_ shold be Vector3 or Line or Plane.
|
170
|
+
# [Output]
|
171
|
+
# [In case _target_ is Vector3]
|
172
|
+
# return "distance, point on triangle" as [Numeric, Vector3].
|
173
|
+
# [In case _target_ is Line]
|
174
|
+
# return "distance, point on tirangle, point on line, parameter on line" as [Numeric, Vector3, Vector3, Numeric].
|
175
|
+
# [In case _target_ is Plane]
|
176
|
+
# return "distance, intersect_line(or closet edge), point_on_triangle, point_on_plane" as [Numeric, Vector3, Vector3, Vector3].
|
177
|
+
def distance(target)
|
178
|
+
# with Point
|
179
|
+
if(target.kind_of?(Vector3))
|
180
|
+
return distance_to_point(target)
|
181
|
+
elsif(target.kind_of?(Line))
|
182
|
+
#with Line
|
183
|
+
return distance_to_line(target)
|
184
|
+
elsif(target.kind_of?(Plane))
|
185
|
+
#with Plane
|
186
|
+
return distance_to_plane(target)
|
187
|
+
end
|
188
|
+
Util3D.raise_argurment_error(target)
|
189
|
+
end
|
190
|
+
|
191
|
+
# [Input]
|
192
|
+
# _check_point_ shold be Vector3.
|
193
|
+
# [Output]
|
194
|
+
# return true if triangle contains _check_point_.
|
195
|
+
def contains?( check_point )
|
196
|
+
Util3D.check_arg_type(Vector3, check_point )
|
197
|
+
plane = Plane.new( vertices[0], self.normal)
|
198
|
+
distance, projected_point = plane.distance(check_point)
|
199
|
+
return false if( distance > self.tolerance )
|
200
|
+
g_coord = self.barycentric_coordinate(check_point)
|
201
|
+
g_coord.each do |item|
|
202
|
+
return false if( item < 0 or 1 < item)
|
203
|
+
end
|
204
|
+
return true
|
205
|
+
end
|
206
|
+
|
207
|
+
private
|
208
|
+
def distance_to_point(target_point)
|
209
|
+
plane = Plane.new( vertices[0], self.normal)
|
210
|
+
distance, projected_point = plane.distance(target_point)
|
211
|
+
if( self.contains?(projected_point))
|
212
|
+
return distance, projected_point
|
213
|
+
end
|
214
|
+
#check distance to FiniteLines
|
215
|
+
finite_lines = self.edges
|
216
|
+
return FiniteLine.ary_distanc_to_point(finite_lines, target_point)
|
217
|
+
end
|
218
|
+
|
219
|
+
def distance_to_line(target_line)
|
220
|
+
plane = Plane.new( vertices[0], self.normal )
|
221
|
+
distance, point_on_plane, parameter_on_line = plane.distance( target_line )
|
222
|
+
if( point_on_plane == nil)
|
223
|
+
# parallel case
|
224
|
+
# check distance to FiniteLines
|
225
|
+
finite_lines = self.edges
|
226
|
+
distance, point_on_edge, point_on_target, param_on_finiteline, param_on_target =
|
227
|
+
FiniteLine.ary_distance_to_line(finite_lines, target_line)
|
228
|
+
return distance, nil, nil, nil
|
229
|
+
end
|
230
|
+
if( self.contains?(point_on_plane) )
|
231
|
+
return distance, point_on_plane, point_on_plane, parameter_on_line
|
232
|
+
end
|
233
|
+
# check distance to FiniteLines
|
234
|
+
finite_lines = self.edges
|
235
|
+
distance, point_on_edge, point_on_target, param_on_finiteline, param_on_target =
|
236
|
+
FiniteLine.ary_distance_to_line(finite_lines, target_line)
|
237
|
+
return distance, point_on_edge, point_on_target, param_on_target
|
238
|
+
end
|
239
|
+
|
240
|
+
def distance_to_plane(target_plane)
|
241
|
+
triangle_plane = Plane.new( vertices[0], self.normal )
|
242
|
+
distance, intersect_line_each_plane = triangle_plane.distance( target_plane )
|
243
|
+
if( intersect_line_each_plane == nil )
|
244
|
+
return distance, nil, nil, nil
|
245
|
+
end
|
246
|
+
|
247
|
+
# check distance from intersection and each edge.
|
248
|
+
distance_zero_count = 0
|
249
|
+
distance_info = Array.new(0)
|
250
|
+
prallel_edge_ary = Array.new(0)
|
251
|
+
self.edges.each do |edge|
|
252
|
+
distance, point_on_edge, point_on_line = edge.distance( intersect_line_each_plane)
|
253
|
+
if point_on_edge != nil && point_on_line != nil
|
254
|
+
distance_info.push([distance, point_on_edge, point_on_line])
|
255
|
+
if distance <= self.tolerance
|
256
|
+
distance_zero_count += 1
|
257
|
+
end
|
258
|
+
else
|
259
|
+
prallel_edge_ary.push( edge )
|
260
|
+
end
|
261
|
+
end
|
262
|
+
distance_info.sort!{|a,b| a[0] <=> b[0]}
|
263
|
+
# distance, intersect_line(or closet edge), point_on_triangle, point_on_plan
|
264
|
+
if (distance_zero_count == 2)
|
265
|
+
point1 = distance_info[0][1]
|
266
|
+
point2 = distance_info[1][1]
|
267
|
+
if point1.distance(point2) > self.tolerance
|
268
|
+
return 0.0, FiniteLine.new(point1, point2), nil, nil
|
269
|
+
end
|
270
|
+
return 0.0, nil, point1, point1
|
271
|
+
elsif (distance_zero_count == 0)
|
272
|
+
distance, closest_point_on_plane = target_plane.distance(distance_info[0][1])
|
273
|
+
if(distance_info[0][1] != distance_info[1][1])
|
274
|
+
return distance, FiniteLine.new(distance_info[0][1], distance_info[1][1]), nil, nil
|
275
|
+
end
|
276
|
+
return distance, nil, distance_info[0][1], closest_point_on_plane
|
277
|
+
end
|
278
|
+
return 0.0, nil, nil, nil
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|