gmath3D 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
data/lib/tri_mesh.rb CHANGED
@@ -1,258 +1,258 @@
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
- include BoxAvailable
12
-
13
- # [Input]
14
- # vertices is Array of Vector3.
15
- # tri_indices is Array of triangle whick is consist of 3 vertices index.
16
- # [Output]
17
- # return new instance of TriMesh.
18
- def initialize(vertices, tri_indices)
19
- # check arg
20
- Util3D.check_arg_type(Array, vertices)
21
- Util3D.check_arg_type(Array, tri_indices)
22
- vertices.each do |item|
23
- Util3D.check_arg_type(Vector3, item)
24
- end
25
- tri_indices.each do |tri_index|
26
- Util3D.check_arg_type(Array, tri_index)
27
- tri_index.each do |item|
28
- Util3D.check_arg_type(Integer, item)
29
- end
30
- end
31
- super()
32
- @vertices = vertices
33
- @tri_indices = tri_indices
34
- end
35
-
36
- def initialize_copy( original_obj )
37
- @vertices = Array.new(original_obj.vertices.size)
38
- for i in 0..@vertices.size-1
39
- @vertices[i] = original_obj.vertices[i].dup
40
- end
41
- @tri_indices = Array.new(original_obj.tri_indices.size)
42
- for i in 0..@tri_indices.size-1
43
- @tri_indices[i] = original_obj.tri_indices[i].dup
44
- end
45
- end
46
-
47
- # [Input]
48
- # _box_ is a Box object.
49
- # [Output]
50
- # return new instance of TriMesh.
51
- def self.from_box(box)
52
- Util3D.check_arg_type(Box, box)
53
- width, height, depth = box.length()
54
- vertices = Array.new(8)
55
- vertices[0] = box.min_point
56
- vertices[1] = box.min_point + Vector3.new(width, 0, 0)
57
- vertices[2] = box.min_point + Vector3.new(width, 0, depth)
58
- vertices[3] = box.min_point + Vector3.new(0 , 0, depth)
59
- vertices[4] = box.min_point + Vector3.new(0 , height, 0)
60
- vertices[5] = box.min_point + Vector3.new(width, height, 0)
61
- vertices[6] = box.min_point + Vector3.new(width, height, depth)
62
- vertices[7] = box.min_point + Vector3.new(0 , height, depth)
63
-
64
- tri_indices =[
65
- [0, 1, 2],
66
- [0, 2, 3],
67
- [1, 5, 6],
68
- [1, 6, 2],
69
- [5, 4, 7],
70
- [5, 7, 6],
71
- [4, 0, 3],
72
- [4, 3, 7],
73
- [2, 6, 7],
74
- [2, 7, 3],
75
- [0, 4, 5],
76
- [0, 5, 1]]
77
- return TriMesh.new( vertices, tri_indices )
78
- end
79
-
80
- # [Input]
81
- # _rect_ is a Rectangle object.
82
- # [Output]
83
- # return new instance of TriMesh.
84
- def self.from_rectangle(rect)
85
- Util3D.check_arg_type(Rectangle, rect)
86
- return TriMesh.new(rect.vertices, [[0,1,3], [1,2,3]])
87
- end
88
-
89
- # [Input]
90
- # _tris_ is Array of Triangle object.
91
- # [Output]
92
- # return new instance of TriMesh
93
- def self.from_triangles(tris)
94
- Util3D.check_arg_type(Array, tris)
95
- tris.each do | item |
96
- Util3D.check_arg_type(Triangle, item)
97
- end
98
-
99
- tri_idx = 0
100
- vert_tris_map = Hash.new(nil)
101
- tris.each_with_index do | triangle, tri_idx |
102
- triangle.vertices.each do | vertex |
103
- vert_tris_map[vertex] = Array.new() if( !vert_tris_map.key?(vertex) )
104
- vert_tris_map[vertex] = vert_tris_map[vertex].push(tri_idx)
105
- end
106
- end
107
-
108
- tri_indices = Array.new( tris.size )
109
- vertices = vert_tris_map.keys
110
-
111
- vert_idx = 0
112
- vert_tris_map.each do | vertex, tri_index_ary |
113
- tri_index_ary.each do | tri_index |
114
- tri_indices[tri_index] = Array.new() if( !tri_indices[tri_index] )
115
- tri_indices[tri_index].push(vert_idx)
116
- end
117
- vert_idx += 1
118
- end
119
-
120
- # modify noamal direction
121
- tri_idx = 0
122
- tri_indices.each do | tri_index_ary |
123
- if ( tri_index_ary.size > 2 )
124
- tmp_tri = Triangle.new(vertices[tri_index_ary[0]], vertices[tri_index_ary[1]], vertices[tri_index_ary[2]])
125
- if( tmp_tri.normal.dot(tris[tri_idx].normal) < 0 )
126
- tri_index_ary.reverse!
127
- end
128
- end
129
- tri_idx += 1
130
- end
131
-
132
- return TriMesh.new( vertices, tri_indices )
133
- end
134
-
135
- # [Input]
136
- # _polyline_ is Poyline object that should be convex.
137
- # [Output]
138
- # return new instance of TriMesh
139
- def self.from_convex_polyline(polyline)
140
- trimesh_vertices = Array.new(polyline.vertices.size + 1)
141
- trimesh_vertices[0] = polyline.center
142
- i = 1
143
- polyline.vertices.each do | poly_vert |
144
- trimesh_vertices[i] = poly_vert.clone
145
- i += 1
146
- end
147
- trimesh_tri_indices = Array.new(polyline.vertices.size)
148
- for i in 0..polyline.vertices.size-1
149
- trimesh_tri_indices[i] = [0,i+1,i+2]
150
- end
151
- trimesh_tri_indices[trimesh_tri_indices.size - 1] = [0,polyline.vertices.size,1]
152
- return TriMesh.new( trimesh_vertices, trimesh_tri_indices )
153
- end
154
-
155
- # [Input]
156
- # _polyline_ is Poyline object.
157
- # _extrude_direction_ is Vector3.
158
- # [Output]
159
- # return new instance of TriMesh that is extruded polyline
160
- def self.from_extrude_polyline(polyline, extrude_direction)
161
- trimesh_vertices = Array.new(polyline.vertices.size*2)
162
- poly_vert_cnt = polyline.vertices.size
163
- i = 0
164
- polyline.vertices.each do | poly_vert |
165
- trimesh_vertices[i] = poly_vert.clone
166
- trimesh_vertices[i + poly_vert_cnt] = poly_vert + extrude_direction
167
- i+=1
168
- end
169
-
170
- tri_indices_cnt = (poly_vert_cnt-1)*2
171
- trimesh_tri_indices = Array.new(tri_indices_cnt)
172
-
173
- for i in 0..poly_vert_cnt-2
174
- trimesh_tri_indices[2*i ] = [i, i + 1, i + poly_vert_cnt]
175
- trimesh_tri_indices[2*i + 1] = [i + 1, i + 1 + poly_vert_cnt, i + poly_vert_cnt]
176
- end
177
- if(!polyline.is_open)
178
- trimesh_tri_indices[2*(poly_vert_cnt - 1) ] = [poly_vert_cnt - 1, 0, 2*(poly_vert_cnt - 1) + 1]
179
- trimesh_tri_indices[2*(poly_vert_cnt - 1) + 1] = [0, poly_vert_cnt, 2*(poly_vert_cnt - 1) + 1]
180
- end
181
- return TriMesh.new(trimesh_vertices, trimesh_tri_indices)
182
- end
183
-
184
- # [Input]
185
- # _rhs_ is TriMesh.
186
- # [Output]
187
- # return true if rhs equals myself.
188
- def ==(rhs)
189
- return false if rhs == nil
190
- return false if( !rhs.kind_of?(TriMesh) )
191
- return false if(@vertices.size != rhs.vertices.size)
192
- return false if(@tri_indices.size != rhs.tri_indices.size)
193
-
194
- for i in 0..(@vertices.size-1)
195
- return false if( @vertices[i] != rhs.vertices[i])
196
- end
197
-
198
- for i in 0..(@tri_indices.size-1)
199
- return false if( @tri_indices[i] != rhs.tri_indices[i])
200
- end
201
- return true
202
- end
203
-
204
- def to_s
205
- "TriMesh[triangle_count:#{tri_indices.size}, vertex_count:#{vertices.size}]"
206
- end
207
-
208
- # [Input]
209
- # _index_ is index of triangle.
210
- # [Output]
211
- # return new instance of Triangle.
212
- def triangle(index)
213
- return nil if( index < 0 || @tri_indices.size <= index )
214
- tri_index = @tri_indices[index]
215
- return Triangle.new(vertices[tri_index[0]], vertices[tri_index[1]], vertices[tri_index[2]])
216
- end
217
-
218
- # [Output]
219
- # return Array of Triangle.
220
- def triangles
221
- tris = Array.new(tri_indices.size)
222
- i = 0
223
- tri_indices.each do |tri_index|
224
- tris[i] = self.triangle(i)
225
- i += 1
226
- end
227
- return tris
228
- end
229
-
230
- # [Output]
231
- # return surface area of TriMesh.
232
- def area
233
- area_sum = 0
234
- triangles.each do | tri |
235
- area_sum += tri.area
236
- end
237
- return area_sum
238
- end
239
-
240
- # [Output]
241
- # return normal vector for each vertex as Hash{ Vector3 vertex => Vector3 normal_vector}.
242
- def normals_for_each_vertices
243
- normals_map = Hash.new(nil)
244
- triangles.each_with_index do | tri, tri_idx |
245
- tri.vertices.each_with_index do | vertex, ver_idx |
246
- normals_map[vertex] = Vector3.new() if( !normals_map.key?(vertex) )
247
- normals_map[vertex] += tri.normal*tri.angle(ver_idx)
248
- end
249
- end
250
- normals_map.each do |vertex, normal|
251
- normals_map[vertex] = normal.normalize
252
- end
253
- return normals_map
254
- end
255
-
256
- end
257
- end
258
-
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
+ include BoxAvailable
12
+
13
+ # [Input]
14
+ # vertices is Array of Vector3.
15
+ # tri_indices is Array of triangle whick is consist of 3 vertices index.
16
+ # [Output]
17
+ # return new instance of TriMesh.
18
+ def initialize(vertices, tri_indices)
19
+ # check arg
20
+ Util3D.check_arg_type(Array, vertices)
21
+ Util3D.check_arg_type(Array, tri_indices)
22
+ vertices.each do |item|
23
+ Util3D.check_arg_type(Vector3, item)
24
+ end
25
+ tri_indices.each do |tri_index|
26
+ Util3D.check_arg_type(Array, tri_index)
27
+ tri_index.each do |item|
28
+ Util3D.check_arg_type(Integer, item)
29
+ end
30
+ end
31
+ super()
32
+ @vertices = vertices
33
+ @tri_indices = tri_indices
34
+ end
35
+
36
+ def initialize_copy( original_obj )
37
+ @vertices = Array.new(original_obj.vertices.size)
38
+ for i in 0..@vertices.size-1
39
+ @vertices[i] = original_obj.vertices[i].dup
40
+ end
41
+ @tri_indices = Array.new(original_obj.tri_indices.size)
42
+ for i in 0..@tri_indices.size-1
43
+ @tri_indices[i] = original_obj.tri_indices[i].dup
44
+ end
45
+ end
46
+
47
+ # [Input]
48
+ # _box_ is a Box object.
49
+ # [Output]
50
+ # return new instance of TriMesh.
51
+ def self.from_box(box)
52
+ Util3D.check_arg_type(Box, box)
53
+ width, height, depth = box.length()
54
+ vertices = Array.new(8)
55
+ vertices[0] = box.min_point
56
+ vertices[1] = box.min_point + Vector3.new(width, 0, 0)
57
+ vertices[2] = box.min_point + Vector3.new(width, 0, depth)
58
+ vertices[3] = box.min_point + Vector3.new(0 , 0, depth)
59
+ vertices[4] = box.min_point + Vector3.new(0 , height, 0)
60
+ vertices[5] = box.min_point + Vector3.new(width, height, 0)
61
+ vertices[6] = box.min_point + Vector3.new(width, height, depth)
62
+ vertices[7] = box.min_point + Vector3.new(0 , height, depth)
63
+
64
+ tri_indices =[
65
+ [0, 1, 2],
66
+ [0, 2, 3],
67
+ [1, 5, 6],
68
+ [1, 6, 2],
69
+ [5, 4, 7],
70
+ [5, 7, 6],
71
+ [4, 0, 3],
72
+ [4, 3, 7],
73
+ [2, 6, 7],
74
+ [2, 7, 3],
75
+ [0, 4, 5],
76
+ [0, 5, 1]]
77
+ return TriMesh.new( vertices, tri_indices )
78
+ end
79
+
80
+ # [Input]
81
+ # _rect_ is a Rectangle object.
82
+ # [Output]
83
+ # return new instance of TriMesh.
84
+ def self.from_rectangle(rect)
85
+ Util3D.check_arg_type(Rectangle, rect)
86
+ return TriMesh.new(rect.vertices, [[0,1,3], [1,2,3]])
87
+ end
88
+
89
+ # [Input]
90
+ # _tris_ is Array of Triangle object.
91
+ # [Output]
92
+ # return new instance of TriMesh
93
+ def self.from_triangles(tris)
94
+ Util3D.check_arg_type(Array, tris)
95
+ tris.each do | item |
96
+ Util3D.check_arg_type(Triangle, item)
97
+ end
98
+
99
+ tri_idx = 0
100
+ vert_tris_map = Hash.new(nil)
101
+ tris.each_with_index do | triangle, tri_idx |
102
+ triangle.vertices.each do | vertex |
103
+ vert_tris_map[vertex] = Array.new() if( !vert_tris_map.key?(vertex) )
104
+ vert_tris_map[vertex] = vert_tris_map[vertex].push(tri_idx)
105
+ end
106
+ end
107
+
108
+ tri_indices = Array.new( tris.size )
109
+ vertices = vert_tris_map.keys
110
+
111
+ vert_idx = 0
112
+ vert_tris_map.each do | vertex, tri_index_ary |
113
+ tri_index_ary.each do | tri_index |
114
+ tri_indices[tri_index] = Array.new() if( !tri_indices[tri_index] )
115
+ tri_indices[tri_index].push(vert_idx)
116
+ end
117
+ vert_idx += 1
118
+ end
119
+
120
+ # modify noamal direction
121
+ tri_idx = 0
122
+ tri_indices.each do | tri_index_ary |
123
+ if ( tri_index_ary.size > 2 )
124
+ tmp_tri = Triangle.new(vertices[tri_index_ary[0]], vertices[tri_index_ary[1]], vertices[tri_index_ary[2]])
125
+ if( tmp_tri.normal.dot(tris[tri_idx].normal) < 0 )
126
+ tri_index_ary.reverse!
127
+ end
128
+ end
129
+ tri_idx += 1
130
+ end
131
+
132
+ return TriMesh.new( vertices, tri_indices )
133
+ end
134
+
135
+ # [Input]
136
+ # _polyline_ is Poyline object that should be convex.
137
+ # [Output]
138
+ # return new instance of TriMesh
139
+ def self.from_convex_polyline(polyline)
140
+ trimesh_vertices = Array.new(polyline.vertices.size + 1)
141
+ trimesh_vertices[0] = polyline.center
142
+ i = 1
143
+ polyline.vertices.each do | poly_vert |
144
+ trimesh_vertices[i] = poly_vert.clone
145
+ i += 1
146
+ end
147
+ trimesh_tri_indices = Array.new(polyline.vertices.size)
148
+ for i in 0..polyline.vertices.size-1
149
+ trimesh_tri_indices[i] = [0,i+1,i+2]
150
+ end
151
+ trimesh_tri_indices[trimesh_tri_indices.size - 1] = [0,polyline.vertices.size,1]
152
+ return TriMesh.new( trimesh_vertices, trimesh_tri_indices )
153
+ end
154
+
155
+ # [Input]
156
+ # _polyline_ is Poyline object.
157
+ # _extrude_direction_ is Vector3.
158
+ # [Output]
159
+ # return new instance of TriMesh that is extruded polyline
160
+ def self.from_extrude_polyline(polyline, extrude_direction)
161
+ trimesh_vertices = Array.new(polyline.vertices.size*2)
162
+ poly_vert_cnt = polyline.vertices.size
163
+ i = 0
164
+ polyline.vertices.each do | poly_vert |
165
+ trimesh_vertices[i] = poly_vert.clone
166
+ trimesh_vertices[i + poly_vert_cnt] = poly_vert + extrude_direction
167
+ i+=1
168
+ end
169
+
170
+ tri_indices_cnt = (poly_vert_cnt-1)*2
171
+ trimesh_tri_indices = Array.new(tri_indices_cnt)
172
+
173
+ for i in 0..poly_vert_cnt-2
174
+ trimesh_tri_indices[2*i ] = [i, i + 1, i + poly_vert_cnt]
175
+ trimesh_tri_indices[2*i + 1] = [i + 1, i + 1 + poly_vert_cnt, i + poly_vert_cnt]
176
+ end
177
+ if(!polyline.is_open)
178
+ trimesh_tri_indices[2*(poly_vert_cnt - 1) ] = [poly_vert_cnt - 1, 0, 2*(poly_vert_cnt - 1) + 1]
179
+ trimesh_tri_indices[2*(poly_vert_cnt - 1) + 1] = [0, poly_vert_cnt, 2*(poly_vert_cnt - 1) + 1]
180
+ end
181
+ return TriMesh.new(trimesh_vertices, trimesh_tri_indices)
182
+ end
183
+
184
+ # [Input]
185
+ # _rhs_ is TriMesh.
186
+ # [Output]
187
+ # return true if rhs equals myself.
188
+ def ==(rhs)
189
+ return false if rhs == nil
190
+ return false if( !rhs.kind_of?(TriMesh) )
191
+ return false if(@vertices.size != rhs.vertices.size)
192
+ return false if(@tri_indices.size != rhs.tri_indices.size)
193
+
194
+ for i in 0..(@vertices.size-1)
195
+ return false if( @vertices[i] != rhs.vertices[i])
196
+ end
197
+
198
+ for i in 0..(@tri_indices.size-1)
199
+ return false if( @tri_indices[i] != rhs.tri_indices[i])
200
+ end
201
+ return true
202
+ end
203
+
204
+ def to_s
205
+ "TriMesh[triangle_count:#{tri_indices.size}, vertex_count:#{vertices.size}]"
206
+ end
207
+
208
+ # [Input]
209
+ # _index_ is index of triangle.
210
+ # [Output]
211
+ # return new instance of Triangle.
212
+ def triangle(index)
213
+ return nil if( index < 0 || @tri_indices.size <= index )
214
+ tri_index = @tri_indices[index]
215
+ return Triangle.new(vertices[tri_index[0]], vertices[tri_index[1]], vertices[tri_index[2]])
216
+ end
217
+
218
+ # [Output]
219
+ # return Array of Triangle.
220
+ def triangles
221
+ tris = Array.new(tri_indices.size)
222
+ i = 0
223
+ tri_indices.each do |tri_index|
224
+ tris[i] = self.triangle(i)
225
+ i += 1
226
+ end
227
+ return tris
228
+ end
229
+
230
+ # [Output]
231
+ # return surface area of TriMesh.
232
+ def area
233
+ area_sum = 0
234
+ triangles.each do | tri |
235
+ area_sum += tri.area
236
+ end
237
+ return area_sum
238
+ end
239
+
240
+ # [Output]
241
+ # return normal vector for each vertex as Hash{ Vector3 vertex => Vector3 normal_vector}.
242
+ def normals_for_each_vertices
243
+ normals_map = Hash.new(nil)
244
+ triangles.each_with_index do | tri, tri_idx |
245
+ tri.vertices.each_with_index do | vertex, ver_idx |
246
+ normals_map[vertex] = Vector3.new() if( !normals_map.key?(vertex) )
247
+ normals_map[vertex] += tri.normal*tri.angle(ver_idx)
248
+ end
249
+ end
250
+ normals_map.each do |vertex, normal|
251
+ normals_map[vertex] = normal.normalize
252
+ end
253
+ return normals_map
254
+ end
255
+
256
+ end
257
+ end
258
+