gmath3D 0.2.1 → 0.2.2
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 -2
- data/lib/box.rb +3 -3
- data/lib/finite_line.rb +6 -1
- data/lib/gmath3D.rb +4 -0
- data/lib/line.rb +17 -0
- data/lib/plane.rb +17 -1
- data/lib/polyline.rb +71 -0
- data/lib/quat.rb +1 -134
- data/lib/rectangle.rb +30 -0
- data/lib/tri_mesh.rb +240 -0
- data/lib/triangle.rb +27 -0
- data/lib/vector3.rb +9 -1
- data/test/test_finite_line.rb +24 -0
- data/test/test_line.rb +33 -0
- data/test/test_plane.rb +33 -0
- data/test/test_polyline.rb +86 -0
- data/test/test_quat.rb +9 -0
- data/test/test_rectangle.rb +45 -0
- data/test/test_tri_mesh.rb +167 -0
- data/test/test_triangle.rb +37 -0
- data/test/test_vector3.rb +65 -0
- metadata +11 -7
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.2
|
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.2"
|
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-25}
|
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 = [
|
@@ -32,8 +32,10 @@ Gem::Specification.new do |s|
|
|
32
32
|
"lib/line.rb",
|
33
33
|
"lib/matrix_util.rb",
|
34
34
|
"lib/plane.rb",
|
35
|
+
"lib/polyline.rb",
|
35
36
|
"lib/quat.rb",
|
36
37
|
"lib/rectangle.rb",
|
38
|
+
"lib/tri_mesh.rb",
|
37
39
|
"lib/triangle.rb",
|
38
40
|
"lib/util.rb",
|
39
41
|
"lib/vector3.rb",
|
@@ -44,8 +46,10 @@ Gem::Specification.new do |s|
|
|
44
46
|
"test/test_line.rb",
|
45
47
|
"test/test_matrix_util.rb",
|
46
48
|
"test/test_plane.rb",
|
49
|
+
"test/test_polyline.rb",
|
47
50
|
"test/test_quat.rb",
|
48
51
|
"test/test_rectangle.rb",
|
52
|
+
"test/test_tri_mesh.rb",
|
49
53
|
"test/test_triangle.rb",
|
50
54
|
"test/test_util.rb",
|
51
55
|
"test/test_vector3.rb"
|
data/lib/box.rb
CHANGED
@@ -6,8 +6,8 @@ module GMath3D
|
|
6
6
|
#
|
7
7
|
class Box < Geom
|
8
8
|
public
|
9
|
-
|
10
|
-
|
9
|
+
attr_reader :min_point
|
10
|
+
attr_reader :max_point
|
11
11
|
|
12
12
|
# [Input]
|
13
13
|
# _point1_ and _point2_ should be Vector3.
|
@@ -51,7 +51,7 @@ public
|
|
51
51
|
end
|
52
52
|
|
53
53
|
# [Output]
|
54
|
-
# return
|
54
|
+
# return width, height, depth as [Numeric, Numeric, Numeric]
|
55
55
|
def length
|
56
56
|
return max_point.x - min_point.x, max_point.y - min_point.y, max_point.z - min_point.z
|
57
57
|
end
|
data/lib/finite_line.rb
CHANGED
@@ -21,6 +21,11 @@ public
|
|
21
21
|
@end_point = end_point
|
22
22
|
end
|
23
23
|
|
24
|
+
def initialize_copy( original_obj )
|
25
|
+
@start_point = original_obj.start_point.dup
|
26
|
+
@end_point = original_obj.end_point.dup
|
27
|
+
end
|
28
|
+
|
24
29
|
def to_s
|
25
30
|
"FiniteLine[from#{start_point.to_element_s}, to#{end_point.to_element_s}]"
|
26
31
|
end
|
@@ -31,7 +36,7 @@ public
|
|
31
36
|
# return true if rhs equals myself.
|
32
37
|
def ==(rhs)
|
33
38
|
return false if rhs == nil
|
34
|
-
|
39
|
+
return false if !rhs.kind_of?(FiniteLine)
|
35
40
|
return false if( self.start_point != rhs.start_point)
|
36
41
|
return false if( self.end_point != rhs.end_point)
|
37
42
|
return true
|
data/lib/gmath3D.rb
CHANGED
data/lib/line.rb
CHANGED
@@ -25,6 +25,23 @@ module GMath3D
|
|
25
25
|
@direction = direction
|
26
26
|
end
|
27
27
|
|
28
|
+
def initialize_copy( original_obj )
|
29
|
+
@base_point = original_obj.base_point.dup
|
30
|
+
@direction = original_obj.direction.dup
|
31
|
+
end
|
32
|
+
|
33
|
+
# [Input]
|
34
|
+
# _rhs_ is Line.
|
35
|
+
# [Output]
|
36
|
+
# return true if rhs equals myself.
|
37
|
+
def ==(rhs)
|
38
|
+
return false if rhs == nil
|
39
|
+
return false if( !rhs.kind_of?(Line) )
|
40
|
+
return false if( self.base_point != rhs.base_point)
|
41
|
+
return false if( self.direction != rhs.direction)
|
42
|
+
return true
|
43
|
+
end
|
44
|
+
|
28
45
|
# [Input]
|
29
46
|
# _parameter_ should be Numeric.
|
30
47
|
# [Output]
|
data/lib/plane.rb
CHANGED
@@ -21,6 +21,23 @@ public
|
|
21
21
|
@normal = normal.normalize()
|
22
22
|
end
|
23
23
|
|
24
|
+
def initialize_copy( original_obj )
|
25
|
+
@base_point = original_obj.base_point.dup
|
26
|
+
@normal = original_obj.normal.dup
|
27
|
+
end
|
28
|
+
|
29
|
+
# [Input]
|
30
|
+
# _rhs_ is Plane.
|
31
|
+
# [Output]
|
32
|
+
# return true if rhs equals myself.
|
33
|
+
def ==(rhs)
|
34
|
+
return false if rhs == nil
|
35
|
+
return false if( !rhs.kind_of?(Plane) )
|
36
|
+
return false if( self.base_point != rhs.base_point)
|
37
|
+
return false if( self.normal != rhs.normal)
|
38
|
+
return true
|
39
|
+
end
|
40
|
+
|
24
41
|
def to_s
|
25
42
|
"Plane[point#{@base_point.to_element_s}, normal#{@normal.to_element_s}]"
|
26
43
|
end
|
@@ -39,7 +56,6 @@ public
|
|
39
56
|
# as [Numeric, Vector3, Vector3, Numeric].
|
40
57
|
# [in case _target_ is Plane]
|
41
58
|
# return "distance, intersect line" as [Numeric, Vector3].
|
42
|
-
|
43
59
|
def distance(target)
|
44
60
|
# with Point
|
45
61
|
if(target.kind_of?(Vector3))
|
data/lib/polyline.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'gmath3D'
|
2
|
+
|
3
|
+
module GMath3D
|
4
|
+
#
|
5
|
+
# Polyline represents a closed or open polyline on 3D space.
|
6
|
+
#
|
7
|
+
class Polyline < Geom
|
8
|
+
public
|
9
|
+
attr_accessor :vertices
|
10
|
+
attr_accessor :is_open
|
11
|
+
|
12
|
+
# [Input]
|
13
|
+
# _vertices_ should be Array of Vector3.
|
14
|
+
# [Output]
|
15
|
+
# return new instance of Polyline.
|
16
|
+
def initialize(vertices = [], is_open = true)
|
17
|
+
Util.check_arg_type(Array, vertices)
|
18
|
+
super()
|
19
|
+
@vertices = vertices
|
20
|
+
@is_open = is_open
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize_copy( original_obj )
|
24
|
+
@vertices = Array.new(original_obj.vertices.size)
|
25
|
+
for i in 0..@vertices.size-1
|
26
|
+
@vertices[i] = original_obj.vertices[i].dup
|
27
|
+
end
|
28
|
+
@is_open = original_obj.is_open
|
29
|
+
end
|
30
|
+
|
31
|
+
# [Input]
|
32
|
+
# _rhs_ is Polyline.
|
33
|
+
# [Output]
|
34
|
+
# return true if rhs equals myself.
|
35
|
+
def ==(rhs)
|
36
|
+
return false if rhs == nil
|
37
|
+
return false if( !rhs.kind_of?(Polyline) )
|
38
|
+
return false if( self.is_open != rhs.is_open )
|
39
|
+
return false if(@vertices.size != rhs.vertices.size)
|
40
|
+
for i in 0..(@vertices.size-1)
|
41
|
+
return false if( self.vertices[i] != rhs.vertices[i])
|
42
|
+
end
|
43
|
+
return true
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_s
|
47
|
+
str = "Polyline["
|
48
|
+
vertices.each do |vertex|
|
49
|
+
str += vertex.to_element_s + ", "
|
50
|
+
end
|
51
|
+
str.slice!(str.length - 2, 2) if(vertices.size > 0)
|
52
|
+
str += "] "
|
53
|
+
str += "open" if(@is_open)
|
54
|
+
str += "closed" if(!@is_open)
|
55
|
+
return str
|
56
|
+
end
|
57
|
+
|
58
|
+
# [Output]
|
59
|
+
# return center point as Vector3.
|
60
|
+
def center
|
61
|
+
center = Vector3.new()
|
62
|
+
@vertices.each do |vertex|
|
63
|
+
center += vertex
|
64
|
+
end
|
65
|
+
center /= @vertices.size
|
66
|
+
return center
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
data/lib/quat.rb
CHANGED
@@ -146,7 +146,7 @@ public
|
|
146
146
|
tf = t1 + t2 + t3
|
147
147
|
rtn_w = self.w * rhs.w - dot
|
148
148
|
|
149
|
-
return Quat.new(tf.x, tf.y, tf.z, rtn_w)
|
149
|
+
return Quat.new(tf.x, tf.y, tf.z, rtn_w)
|
150
150
|
end
|
151
151
|
|
152
152
|
# [Input]
|
@@ -165,139 +165,6 @@ public
|
|
165
165
|
z = pw * qz + px * qy - py * qx + pz * qw
|
166
166
|
return Quat.new( x,y,z,w )
|
167
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
168
|
end
|
302
169
|
end
|
303
170
|
|
data/lib/rectangle.rb
CHANGED
@@ -27,6 +27,25 @@ public
|
|
27
27
|
self.v_vector = v_vector_arg
|
28
28
|
end
|
29
29
|
|
30
|
+
def initialize_copy( original_obj )
|
31
|
+
@base_point = original_obj.base_point.dup
|
32
|
+
@u_vector = original_obj.u_vector.dup
|
33
|
+
@v_vector = original_obj.v_vector.dup
|
34
|
+
end
|
35
|
+
|
36
|
+
# [Input]
|
37
|
+
# _rhs_ is Rectangle.
|
38
|
+
# [Output]
|
39
|
+
# return true if rhs equals myself.
|
40
|
+
def ==(rhs)
|
41
|
+
return false if rhs == nil
|
42
|
+
return false if( !rhs.kind_of?(Rectangle) )
|
43
|
+
return false if( self.base_point != rhs.base_point)
|
44
|
+
return false if( self.u_vector != rhs.u_vector)
|
45
|
+
return false if( self.v_vector != rhs.v_vector)
|
46
|
+
return true
|
47
|
+
end
|
48
|
+
|
30
49
|
def to_s
|
31
50
|
"Rectangle[base#{@base_point.to_element_s}, u#{@u_vector.to_element_s}, v#{@v_vector.to_element_s}"
|
32
51
|
end
|
@@ -52,6 +71,17 @@ public
|
|
52
71
|
return edge_ary
|
53
72
|
end
|
54
73
|
|
74
|
+
# [Output]
|
75
|
+
# return vertices of rectangle as Array of Vector3.
|
76
|
+
def vertices
|
77
|
+
vertices = Array.new(4)
|
78
|
+
vertices[0] = base_point
|
79
|
+
vertices[1] = base_point+u_vector
|
80
|
+
vertices[2] = base_point+u_vector+v_vector
|
81
|
+
vertices[3] = base_point+v_vector
|
82
|
+
return vertices
|
83
|
+
end
|
84
|
+
|
55
85
|
# [Output]
|
56
86
|
# return normal of rectangle as Vector3.
|
57
87
|
def normal
|
data/lib/tri_mesh.rb
ADDED
@@ -0,0 +1,240 @@
|
|
1
|
+
require 'gmath3D'
|
2
|
+
|
3
|
+
module GMath3D
|
4
|
+
#
|
5
|
+
# TriMesh represents an structured trianglular mesh.
|
6
|
+
#
|
7
|
+
class TriMesh < Geom
|
8
|
+
attr_reader :vertices
|
9
|
+
attr_reader :tri_indices
|
10
|
+
|
11
|
+
# [Input]
|
12
|
+
# vertices is Array of Vector3.
|
13
|
+
# tri_indices is Array of triangle whick is consist of 3 vertices index.
|
14
|
+
# [Output]
|
15
|
+
# return new instance of TriMesh.
|
16
|
+
def initialize(vertices, tri_indices)
|
17
|
+
# check arg
|
18
|
+
Util.check_arg_type(Array, vertices)
|
19
|
+
Util.check_arg_type(Array, tri_indices)
|
20
|
+
vertices.each do |item|
|
21
|
+
Util.check_arg_type(Vector3, item)
|
22
|
+
end
|
23
|
+
tri_indices.each do |tri_index|
|
24
|
+
Util.check_arg_type(Array, tri_index)
|
25
|
+
tri_index.each do |item|
|
26
|
+
Util.check_arg_type(Integer, item)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
super()
|
30
|
+
@vertices = vertices
|
31
|
+
@tri_indices = tri_indices
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize_copy( original_obj )
|
35
|
+
@vertices = Array.new(original_obj.vertices.size)
|
36
|
+
for i in 0..@vertices.size-1
|
37
|
+
@vertices[i] = original_obj.vertices[i].dup
|
38
|
+
end
|
39
|
+
@tri_indices = Array.new(original_obj.tri_indices.size)
|
40
|
+
for i in 0..@tri_indices.size-1
|
41
|
+
@tri_indices[i] = original_obj.tri_indices[i].dup
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# [Input]
|
46
|
+
# _box_ is a Box object.
|
47
|
+
# [Output]
|
48
|
+
# return new instance of TriMesh.
|
49
|
+
def self.from_box(box)
|
50
|
+
Util.check_arg_type(Box, box)
|
51
|
+
width, height, depth = box.length()
|
52
|
+
vertices = Array.new(8)
|
53
|
+
vertices[0] = box.min_point
|
54
|
+
vertices[1] = box.min_point + Vector3.new(width, 0, 0)
|
55
|
+
vertices[2] = box.min_point + Vector3.new(width, 0, depth)
|
56
|
+
vertices[3] = box.min_point + Vector3.new(0 , 0, depth)
|
57
|
+
vertices[4] = box.min_point + Vector3.new(0 , height, 0)
|
58
|
+
vertices[5] = box.min_point + Vector3.new(width, height, 0)
|
59
|
+
vertices[6] = box.min_point + Vector3.new(width, height, depth)
|
60
|
+
vertices[7] = box.min_point + Vector3.new(0 , height, depth)
|
61
|
+
|
62
|
+
tri_indices =[
|
63
|
+
[0, 1, 2],
|
64
|
+
[0, 2, 3],
|
65
|
+
[1, 5, 6],
|
66
|
+
[1, 6, 2],
|
67
|
+
[5, 4, 7],
|
68
|
+
[5, 7, 6],
|
69
|
+
[4, 0, 3],
|
70
|
+
[4, 3, 7],
|
71
|
+
[2, 6, 7],
|
72
|
+
[2, 7, 3],
|
73
|
+
[0, 4, 5],
|
74
|
+
[0, 5, 1]]
|
75
|
+
return TriMesh.new( vertices, tri_indices )
|
76
|
+
end
|
77
|
+
|
78
|
+
# [Input]
|
79
|
+
# _rect_ is a Rectangle object.
|
80
|
+
# [Output]
|
81
|
+
# return new instance of TriMesh.
|
82
|
+
def self.from_rectangle(rect)
|
83
|
+
Util.check_arg_type(Rectangle, rect)
|
84
|
+
return TriMesh.new(rect.vertices, [[0,1,3], [1,2,3]])
|
85
|
+
end
|
86
|
+
|
87
|
+
# [Input]
|
88
|
+
# _tris_ is Array of Triangle object.
|
89
|
+
# [Output]
|
90
|
+
# return new instance of TriMesh
|
91
|
+
def self.from_triangles(tris)
|
92
|
+
Util.check_arg_type(Array, tris)
|
93
|
+
tris.each do | item |
|
94
|
+
Util.check_arg_type(Triangle, item)
|
95
|
+
end
|
96
|
+
|
97
|
+
tri_idx = 0
|
98
|
+
vert_tris_map = Hash.new(nil)
|
99
|
+
tris.each do | triangle |
|
100
|
+
triangle.vertices.each do | vertex |
|
101
|
+
vert_tris_map[vertex] = Array.new() if( !vert_tris_map.key?(vertex) )
|
102
|
+
vert_tris_map[vertex] = vert_tris_map[vertex].push(tri_idx)
|
103
|
+
end
|
104
|
+
tri_idx += 1
|
105
|
+
end
|
106
|
+
|
107
|
+
tri_indices = Array.new( tris.size )
|
108
|
+
vertices = vert_tris_map.keys
|
109
|
+
|
110
|
+
vert_idx = 0
|
111
|
+
vert_tris_map.each do | vertex, tri_index_ary |
|
112
|
+
tri_index_ary.each do | tri_index |
|
113
|
+
tri_indices[tri_index] = Array.new() if( !tri_indices[tri_index] )
|
114
|
+
tri_indices[tri_index].push(vert_idx)
|
115
|
+
end
|
116
|
+
vert_idx += 1
|
117
|
+
end
|
118
|
+
|
119
|
+
# modify noamal direction
|
120
|
+
tri_idx = 0
|
121
|
+
tri_indices.each do | tri_index_ary |
|
122
|
+
if ( tri_index_ary.size > 2 )
|
123
|
+
tmp_tri = Triangle.new(vertices[tri_index_ary[0]], vertices[tri_index_ary[1]], vertices[tri_index_ary[2]])
|
124
|
+
if( tmp_tri.normal.dot(tris[tri_idx].normal) < 0 )
|
125
|
+
tri_index_ary.reverse!
|
126
|
+
end
|
127
|
+
end
|
128
|
+
tri_idx += 1
|
129
|
+
end
|
130
|
+
|
131
|
+
return TriMesh.new( vertices, tri_indices )
|
132
|
+
end
|
133
|
+
|
134
|
+
# [Input]
|
135
|
+
# _polyline_ is Poyline object that should be convex.
|
136
|
+
# [Output]
|
137
|
+
# return new instance of TriMesh
|
138
|
+
def self.from_convex_polyline(polyline)
|
139
|
+
trimesh_vertices = Array.new(polyline.vertices.size + 1)
|
140
|
+
trimesh_vertices[0] = polyline.center
|
141
|
+
i = 1
|
142
|
+
polyline.vertices.each do | poly_vert |
|
143
|
+
trimesh_vertices[i] = poly_vert.clone
|
144
|
+
i += 1
|
145
|
+
end
|
146
|
+
trimesh_tri_indices = Array.new(polyline.vertices.size)
|
147
|
+
for i in 0..polyline.vertices.size-1
|
148
|
+
trimesh_tri_indices[i] = [0,i+1,i+2]
|
149
|
+
end
|
150
|
+
trimesh_tri_indices[trimesh_tri_indices.size - 1] = [0,polyline.vertices.size,1]
|
151
|
+
return TriMesh.new( trimesh_vertices, trimesh_tri_indices )
|
152
|
+
end
|
153
|
+
|
154
|
+
# [Input]
|
155
|
+
# _polyline_ is Poyline object.
|
156
|
+
# _extrude_direction_ is Vector3.
|
157
|
+
# [Output]
|
158
|
+
# return new instance of TriMesh that is extruded polyline
|
159
|
+
def self.from_extrude_polyline(polyline, extrude_direction)
|
160
|
+
trimesh_vertices = Array.new(polyline.vertices.size*2)
|
161
|
+
poly_vert_cnt = polyline.vertices.size
|
162
|
+
i = 0
|
163
|
+
polyline.vertices.each do | poly_vert |
|
164
|
+
trimesh_vertices[i] = poly_vert.clone
|
165
|
+
trimesh_vertices[i + poly_vert_cnt] = poly_vert + extrude_direction
|
166
|
+
i+=1
|
167
|
+
end
|
168
|
+
|
169
|
+
tri_indices_cnt = (poly_vert_cnt-1)*2
|
170
|
+
trimesh_tri_indices = Array.new(tri_indices_cnt)
|
171
|
+
|
172
|
+
for i in 0..poly_vert_cnt-2
|
173
|
+
trimesh_tri_indices[2*i ] = [i, i + 1, i + poly_vert_cnt]
|
174
|
+
trimesh_tri_indices[2*i + 1] = [i + 1, i + 1 + poly_vert_cnt, i + poly_vert_cnt]
|
175
|
+
end
|
176
|
+
if(!polyline.is_open)
|
177
|
+
trimesh_tri_indices[2*(poly_vert_cnt - 1) ] = [poly_vert_cnt - 1, 0, 2*(poly_vert_cnt - 1) + 1]
|
178
|
+
trimesh_tri_indices[2*(poly_vert_cnt - 1) + 1] = [0, poly_vert_cnt, 2*(poly_vert_cnt - 1) + 1]
|
179
|
+
end
|
180
|
+
return TriMesh.new(trimesh_vertices, trimesh_tri_indices)
|
181
|
+
end
|
182
|
+
|
183
|
+
# [Input]
|
184
|
+
# _rhs_ is TriMesh.
|
185
|
+
# [Output]
|
186
|
+
# return true if rhs equals myself.
|
187
|
+
def ==(rhs)
|
188
|
+
return false if rhs == nil
|
189
|
+
return false if( !rhs.kind_of?(TriMesh) )
|
190
|
+
return false if(@vertices.size != rhs.vertices.size)
|
191
|
+
return false if(@tri_indices.size != rhs.tri_indices.size)
|
192
|
+
|
193
|
+
for i in 0..(@vertices.size-1)
|
194
|
+
return false if( @vertices[i] != rhs.vertices[i])
|
195
|
+
end
|
196
|
+
|
197
|
+
for i in 0..(@tri_indices.size-1)
|
198
|
+
return false if( @tri_indices[i] != rhs.tri_indices[i])
|
199
|
+
end
|
200
|
+
return true
|
201
|
+
end
|
202
|
+
|
203
|
+
def to_s
|
204
|
+
"TriMesh[triangle_count:#{tri_indices.size}, vertex_count:#{vertices.size}]"
|
205
|
+
end
|
206
|
+
|
207
|
+
# [Input]
|
208
|
+
# _index_ is index of triangle.
|
209
|
+
# [Output]
|
210
|
+
# return new instance of Triangle.
|
211
|
+
def triangle(index)
|
212
|
+
return nil if( index < 0 || @tri_indices.size <= index )
|
213
|
+
tri_index = @tri_indices[index]
|
214
|
+
return Triangle.new(vertices[tri_index[0]], vertices[tri_index[1]], vertices[tri_index[2]])
|
215
|
+
end
|
216
|
+
|
217
|
+
# [Output]
|
218
|
+
# return Array of Triangle.
|
219
|
+
def triangles
|
220
|
+
tris = Array.new(tri_indices.size)
|
221
|
+
i = 0
|
222
|
+
tri_indices.each do |tri_index|
|
223
|
+
tris[i] = self.triangle(i)
|
224
|
+
i += 1
|
225
|
+
end
|
226
|
+
return tris
|
227
|
+
end
|
228
|
+
|
229
|
+
# [Output]
|
230
|
+
# return surface area of TriMesh.
|
231
|
+
def area
|
232
|
+
area_sum = 0
|
233
|
+
triangles.each do | tri |
|
234
|
+
area_sum += tri.area
|
235
|
+
end
|
236
|
+
return area_sum
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
data/lib/triangle.rb
CHANGED
@@ -20,6 +20,27 @@ public
|
|
20
20
|
@vertices = Array.new([vertex1, vertex2, vertex3])
|
21
21
|
end
|
22
22
|
|
23
|
+
def initialize_copy( original_obj )
|
24
|
+
@vertices = Array.new(original_obj.vertices.size)
|
25
|
+
for i in 0..@vertices.size-1
|
26
|
+
@vertices[i] = original_obj.vertices[i].dup
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# [Input]
|
31
|
+
# _rhs_ is Line.
|
32
|
+
# [Output]
|
33
|
+
# return true if rhs equals myself.
|
34
|
+
def ==(rhs)
|
35
|
+
return false if rhs == nil
|
36
|
+
return false if( !rhs.kind_of?(Triangle) )
|
37
|
+
return false if(@vertices.size != rhs.vertices.size)
|
38
|
+
for i in 0..@vertices.size-1
|
39
|
+
return false if(@vertices[i] != rhs.vertices[i])
|
40
|
+
end
|
41
|
+
return true
|
42
|
+
end
|
43
|
+
|
23
44
|
def to_s
|
24
45
|
"Triangle[#{@vertices[0].to_element_s}, #{@vertices[1].to_element_s}, #{@vertices[2].to_element_s}]"
|
25
46
|
end
|
@@ -67,6 +88,12 @@ public
|
|
67
88
|
return (vec1.cross(vec2).normalize)
|
68
89
|
end
|
69
90
|
|
91
|
+
# [Output]
|
92
|
+
# return normal vector reversed triangle
|
93
|
+
def reverse()
|
94
|
+
return Triangle.new(@vertices[0], @vertices[2], @vertices[1])
|
95
|
+
end
|
96
|
+
|
70
97
|
# [Input]
|
71
98
|
# _check_point_ should be Vector3.
|
72
99
|
# [Output]
|