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/lib/rectangle.rb CHANGED
@@ -1,155 +1,155 @@
1
- require 'matrix'
2
-
3
- require 'gmath3D'
4
-
5
- module GMath3D
6
- #
7
- # Rectangle represents a four edged finite plane on 3D space.
8
- #
9
- class Rectangle < Geom
10
- public
11
- attr_accessor:base_point
12
- attr_accessor:u_vector
13
- attr_accessor:v_vector
14
-
15
- include BoxAvailable
16
-
17
- # [Input]
18
- # _base_point_ , _u_vector_, _v_vector_ should be Vector3.
19
- # _u_vector_ and _v_vector_ should be orthogonalized.
20
- # [Output]
21
- # return new instance of Rectangle.
22
- def initialize(base_point_arg = Vector3.new(), u_vector_arg = Vector3.new(1,0,0), v_vector_arg = Vector3.new(0,1,0))
23
- Util3D.check_arg_type(::Vector3, base_point_arg)
24
- Util3D.check_arg_type(::Vector3, u_vector_arg)
25
- Util3D.check_arg_type(::Vector3, v_vector_arg)
26
- super()
27
- self.base_point = base_point_arg
28
- self.u_vector = u_vector_arg
29
- self.v_vector = v_vector_arg
30
- end
31
-
32
- def initialize_copy( original_obj )
33
- @base_point = original_obj.base_point.dup
34
- @u_vector = original_obj.u_vector.dup
35
- @v_vector = original_obj.v_vector.dup
36
- end
37
-
38
- # [Input]
39
- # _rhs_ is Rectangle.
40
- # [Output]
41
- # return true if rhs equals myself.
42
- def ==(rhs)
43
- return false if rhs == nil
44
- return false if( !rhs.kind_of?(Rectangle) )
45
- return false if( self.base_point != rhs.base_point)
46
- return false if( self.u_vector != rhs.u_vector)
47
- return false if( self.v_vector != rhs.v_vector)
48
- return true
49
- end
50
-
51
- def to_s
52
- "Rectangle[base#{@base_point.to_element_s}, u#{@u_vector.to_element_s}, v#{@v_vector.to_element_s}"
53
- end
54
-
55
- # [Input]
56
- # _u_, _v_ should be Numeric.
57
- # [Output]
58
- # return point on rectangle as Vector3.
59
- def point(u, v)
60
- Util3D.check_arg_type(::Numeric, u)
61
- Util3D.check_arg_type(::Numeric, v)
62
- return base_point + u_vector*u + v_vector*v
63
- end
64
-
65
- # [Output]
66
- # return edges of rectangle as Array of FiniteLine.
67
- def edges
68
- edge_ary = Array.new(4)
69
- edge_ary[0] = FiniteLine.new( base_point, base_point+u_vector)
70
- edge_ary[1] = FiniteLine.new( base_point+u_vector, base_point+u_vector+v_vector)
71
- edge_ary[2] = FiniteLine.new( base_point+u_vector+v_vector, base_point+v_vector)
72
- edge_ary[3] = FiniteLine.new( base_point+v_vector, base_point)
73
- return edge_ary
74
- end
75
-
76
- # [Output]
77
- # return vertices of rectangle as Array of Vector3.
78
- def vertices
79
- vertices = Array.new(4)
80
- vertices[0] = base_point
81
- vertices[1] = base_point+u_vector
82
- vertices[2] = base_point+u_vector+v_vector
83
- vertices[3] = base_point+v_vector
84
- return vertices
85
- end
86
-
87
- # [Output]
88
- # return normal of rectangle as Vector3.
89
- def normal
90
- return (u_vector.cross(v_vector)).normalize()
91
- end
92
-
93
- # [Output]
94
- # return point of opposite to base_point as Vector3.
95
- def opposite_point
96
- return base_point + u_vector + v_vector
97
- end
98
-
99
- # [Output]
100
- # return center point as Vector3.
101
- def center_point
102
- return base_point + u_vector*0.5 + v_vector*0.5
103
- end
104
-
105
- # [Output]
106
- # return rectangle area as Numeric.
107
- def area
108
- return (u_vector.cross(v_vector)).length
109
- end
110
-
111
- # [Input]
112
- # _check_point_ shold be Vector3.
113
- # [Output]
114
- # return u, v parametes on check_point as [Numeric, Numeric].
115
- def uv_parameter(check_point)
116
- Util3D.check_arg_type(::Vector3, check_point)
117
- mat = Matrix[[u_vector.x, u_vector.y, u_vector.z],
118
- [v_vector.x, v_vector.y, v_vector.z],
119
- [normal.x, normal.y, normal.z]]
120
- vec = (check_point - base_point).to_column_vector
121
- ans = mat.t.inv*vec
122
- return ans[0,0], ans[1,0]
123
- end
124
-
125
- # [Input]
126
- # _target_ shold be Vector3.
127
- # [Output]
128
- # return "distance, point on rectangle" as [Numeric, Vector3].
129
- def distance(target)
130
- # with Point
131
- if(target.kind_of?(Vector3))
132
- return distance_to_point(target)
133
- elsif(target.kind_of?(Line))
134
- #with Line
135
- # return distance_to_line(target)
136
- end
137
- Util3D.raise_argurment_error(target)
138
- end
139
-
140
- private
141
- def distance_to_point(check_point)
142
- u,v = self.uv_parameter(check_point)
143
- if(u >= 0 && u <= 1 && v >= 0 && v <= 1)
144
- point_on_rect = self.point( u, v )
145
- distance = point_on_rect.distance(check_point)
146
- return distance, point_on_rect
147
- end
148
- # rectangle does not contain projected point
149
- # check distance to FiniteLines
150
- finite_lines = self.edges
151
- return FiniteLine.ary_distanc_to_point(finite_lines, check_point)
152
- end
153
- end
154
- end
155
-
1
+ require 'matrix'
2
+
3
+ require 'gmath3D'
4
+
5
+ module GMath3D
6
+ #
7
+ # Rectangle represents a four edged finite plane on 3D space.
8
+ #
9
+ class Rectangle < Geom
10
+ public
11
+ attr_accessor:base_point
12
+ attr_accessor:u_vector
13
+ attr_accessor:v_vector
14
+
15
+ include BoxAvailable
16
+
17
+ # [Input]
18
+ # _base_point_ , _u_vector_, _v_vector_ should be Vector3.
19
+ # _u_vector_ and _v_vector_ should be orthogonalized.
20
+ # [Output]
21
+ # return new instance of Rectangle.
22
+ def initialize(base_point_arg = Vector3.new(), u_vector_arg = Vector3.new(1,0,0), v_vector_arg = Vector3.new(0,1,0))
23
+ Util3D.check_arg_type(::Vector3, base_point_arg)
24
+ Util3D.check_arg_type(::Vector3, u_vector_arg)
25
+ Util3D.check_arg_type(::Vector3, v_vector_arg)
26
+ super()
27
+ self.base_point = base_point_arg
28
+ self.u_vector = u_vector_arg
29
+ self.v_vector = v_vector_arg
30
+ end
31
+
32
+ def initialize_copy( original_obj )
33
+ @base_point = original_obj.base_point.dup
34
+ @u_vector = original_obj.u_vector.dup
35
+ @v_vector = original_obj.v_vector.dup
36
+ end
37
+
38
+ # [Input]
39
+ # _rhs_ is Rectangle.
40
+ # [Output]
41
+ # return true if rhs equals myself.
42
+ def ==(rhs)
43
+ return false if rhs == nil
44
+ return false if( !rhs.kind_of?(Rectangle) )
45
+ return false if( self.base_point != rhs.base_point)
46
+ return false if( self.u_vector != rhs.u_vector)
47
+ return false if( self.v_vector != rhs.v_vector)
48
+ return true
49
+ end
50
+
51
+ def to_s
52
+ "Rectangle[base#{@base_point.to_element_s}, u#{@u_vector.to_element_s}, v#{@v_vector.to_element_s}"
53
+ end
54
+
55
+ # [Input]
56
+ # _u_, _v_ should be Numeric.
57
+ # [Output]
58
+ # return point on rectangle as Vector3.
59
+ def point(u, v)
60
+ Util3D.check_arg_type(::Numeric, u)
61
+ Util3D.check_arg_type(::Numeric, v)
62
+ return base_point + u_vector*u + v_vector*v
63
+ end
64
+
65
+ # [Output]
66
+ # return edges of rectangle as Array of FiniteLine.
67
+ def edges
68
+ edge_ary = Array.new(4)
69
+ edge_ary[0] = FiniteLine.new( base_point, base_point+u_vector)
70
+ edge_ary[1] = FiniteLine.new( base_point+u_vector, base_point+u_vector+v_vector)
71
+ edge_ary[2] = FiniteLine.new( base_point+u_vector+v_vector, base_point+v_vector)
72
+ edge_ary[3] = FiniteLine.new( base_point+v_vector, base_point)
73
+ return edge_ary
74
+ end
75
+
76
+ # [Output]
77
+ # return vertices of rectangle as Array of Vector3.
78
+ def vertices
79
+ vertices = Array.new(4)
80
+ vertices[0] = base_point
81
+ vertices[1] = base_point+u_vector
82
+ vertices[2] = base_point+u_vector+v_vector
83
+ vertices[3] = base_point+v_vector
84
+ return vertices
85
+ end
86
+
87
+ # [Output]
88
+ # return normal of rectangle as Vector3.
89
+ def normal
90
+ return (u_vector.cross(v_vector)).normalize()
91
+ end
92
+
93
+ # [Output]
94
+ # return point of opposite to base_point as Vector3.
95
+ def opposite_point
96
+ return base_point + u_vector + v_vector
97
+ end
98
+
99
+ # [Output]
100
+ # return center point as Vector3.
101
+ def center_point
102
+ return base_point + u_vector*0.5 + v_vector*0.5
103
+ end
104
+
105
+ # [Output]
106
+ # return rectangle area as Numeric.
107
+ def area
108
+ return (u_vector.cross(v_vector)).length
109
+ end
110
+
111
+ # [Input]
112
+ # _check_point_ shold be Vector3.
113
+ # [Output]
114
+ # return u, v parametes on check_point as [Numeric, Numeric].
115
+ def uv_parameter(check_point)
116
+ Util3D.check_arg_type(::Vector3, check_point)
117
+ mat = Matrix[[u_vector.x, u_vector.y, u_vector.z],
118
+ [v_vector.x, v_vector.y, v_vector.z],
119
+ [normal.x, normal.y, normal.z]]
120
+ vec = (check_point - base_point).to_column_vector
121
+ ans = mat.t.inv*vec
122
+ return ans[0,0], ans[1,0]
123
+ end
124
+
125
+ # [Input]
126
+ # _target_ shold be Vector3.
127
+ # [Output]
128
+ # return "distance, point on rectangle" as [Numeric, Vector3].
129
+ def distance(target)
130
+ # with Point
131
+ if(target.kind_of?(Vector3))
132
+ return distance_to_point(target)
133
+ elsif(target.kind_of?(Line))
134
+ #with Line
135
+ # return distance_to_line(target)
136
+ end
137
+ Util3D.raise_argurment_error(target)
138
+ end
139
+
140
+ private
141
+ def distance_to_point(check_point)
142
+ u,v = self.uv_parameter(check_point)
143
+ if(u >= 0 && u <= 1 && v >= 0 && v <= 1)
144
+ point_on_rect = self.point( u, v )
145
+ distance = point_on_rect.distance(check_point)
146
+ return distance, point_on_rect
147
+ end
148
+ # rectangle does not contain projected point
149
+ # check distance to FiniteLines
150
+ finite_lines = self.edges
151
+ return FiniteLine.ary_distanc_to_point(finite_lines, check_point)
152
+ end
153
+ end
154
+ end
155
+
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
+