Class: GMath3D::TriMesh

Inherits:
Geom
  • Object
show all
Includes:
BoxAvailable
Defined in:
lib/tri_mesh.rb

Overview

TriMesh represents an structured trianglular mesh.

Instance Attribute Summary collapse

Attributes inherited from Geom

#tolerance

Class Method Summary collapse

Instance Method Summary collapse

Methods included from BoxAvailable

#box

Methods inherited from Geom

default_tolerance

Constructor Details

#initialize(vertices, tri_indices) ⇒ TriMesh

Input

vertices is Array of Vector3. tri_indices is Array of triangle whick is consist of 3 vertices index.

Output

return new instance of TriMesh.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/tri_mesh.rb', line 18

def initialize(vertices, tri_indices)
  # check arg
  Util3D.check_arg_type(Array, vertices)
  Util3D.check_arg_type(Array, tri_indices)
  vertices.each do |item|
    Util3D.check_arg_type(Vector3, item)
  end
  tri_indices.each do |tri_index|
    Util3D.check_arg_type(Array, tri_index)
    tri_index.each do |item|
      Util3D.check_arg_type(Integer, item)
    end
  end
  super()
  @vertices = vertices
  @tri_indices = tri_indices
end

Instance Attribute Details

#tri_indicesObject (readonly)

Returns the value of attribute tri_indices.



9
10
11
# File 'lib/tri_mesh.rb', line 9

def tri_indices
  @tri_indices
end

#verticesObject (readonly)

Returns the value of attribute vertices.



8
9
10
# File 'lib/tri_mesh.rb', line 8

def vertices
  @vertices
end

Class Method Details

.from_box(box) ⇒ Object

Input

box is a Box object.

Output

return new instance of TriMesh.



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/tri_mesh.rb', line 51

def self.from_box(box)
  Util3D.check_arg_type(Box, box)
  width, height, depth = box.length()
  vertices = Array.new(8)
  vertices[0] = box.min_point
  vertices[1] = box.min_point + Vector3.new(width, 0, 0)
  vertices[2] = box.min_point + Vector3.new(width, 0, depth)
  vertices[3] = box.min_point + Vector3.new(0    , 0, depth)
  vertices[4] = box.min_point + Vector3.new(0    , height, 0)
  vertices[5] = box.min_point + Vector3.new(width, height, 0)
  vertices[6] = box.min_point + Vector3.new(width, height, depth)
  vertices[7] = box.min_point + Vector3.new(0    , height, depth)

  tri_indices =[
    [0, 1, 2],
    [0, 2, 3],
    [1, 5, 6],
    [1, 6, 2],
    [5, 4, 7],
    [5, 7, 6],
    [4, 0, 3],
    [4, 3, 7],
    [2, 6, 7],
    [2, 7, 3],
    [0, 4, 5],
    [0, 5, 1]]
  return TriMesh.new( vertices, tri_indices )
end

.from_convex_polyline(polyline) ⇒ Object

Input

polyline is Poyline object that should be convex.

Output

return new instance of TriMesh



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/tri_mesh.rb', line 139

def self.from_convex_polyline(polyline)
  trimesh_vertices = Array.new(polyline.vertices.size + 1)
  trimesh_vertices[0] = polyline.center
  i = 1
  polyline.vertices.each do | poly_vert |
    trimesh_vertices[i] = poly_vert.clone
    i += 1
  end
  trimesh_tri_indices = Array.new(polyline.vertices.size)
  for i in 0..polyline.vertices.size-1
    trimesh_tri_indices[i] = [0,i+1,i+2]
  end
  trimesh_tri_indices[trimesh_tri_indices.size - 1] = [0,polyline.vertices.size,1]
  return TriMesh.new( trimesh_vertices, trimesh_tri_indices )
end

.from_extrude_polyline(polyline, extrude_direction) ⇒ Object

Input

polyline is Poyline object. extrude_direction is Vector3.

Output

return new instance of TriMesh that is extruded polyline



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/tri_mesh.rb', line 160

def self.from_extrude_polyline(polyline, extrude_direction)
  trimesh_vertices = Array.new(polyline.vertices.size*2)
  poly_vert_cnt = polyline.vertices.size
  i = 0
  polyline.vertices.each do | poly_vert |
    trimesh_vertices[i] = poly_vert.clone
    trimesh_vertices[i + poly_vert_cnt] = poly_vert + extrude_direction
    i+=1
  end

  tri_indices_cnt = (poly_vert_cnt-1)*2
  trimesh_tri_indices = Array.new(tri_indices_cnt)

  for i in 0..poly_vert_cnt-2
    trimesh_tri_indices[2*i    ] = [i,     i + 1,                 i + poly_vert_cnt]
    trimesh_tri_indices[2*i + 1] = [i + 1, i + 1 + poly_vert_cnt, i + poly_vert_cnt]
  end
  if(!polyline.is_open)
    trimesh_tri_indices[2*(poly_vert_cnt - 1)    ] = [poly_vert_cnt - 1, 0, 2*(poly_vert_cnt - 1) + 1]
    trimesh_tri_indices[2*(poly_vert_cnt - 1) + 1] = [0, poly_vert_cnt, 2*(poly_vert_cnt - 1) + 1]
  end
  return TriMesh.new(trimesh_vertices, trimesh_tri_indices)
end

.from_rectangle(rect) ⇒ Object

Input

rect is a Rectangle object.

Output

return new instance of TriMesh.



84
85
86
87
# File 'lib/tri_mesh.rb', line 84

def self.from_rectangle(rect)
  Util3D.check_arg_type(Rectangle, rect)
  return TriMesh.new(rect.vertices, [[0,1,3], [1,2,3]])
end

.from_triangles(tris) ⇒ Object

Input

tris is Array of Triangle object.

Output

return new instance of TriMesh



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/tri_mesh.rb', line 93

def self.from_triangles(tris)
  Util3D.check_arg_type(Array, tris)
  tris.each do | item |
    Util3D.check_arg_type(Triangle, item)
  end

  tri_idx = 0
  vert_tris_map = Hash.new(nil)
  tris.each_with_index do | triangle, tri_idx |
    triangle.vertices.each do | vertex |
      vert_tris_map[vertex] = Array.new() if( !vert_tris_map.key?(vertex) )
      vert_tris_map[vertex] = vert_tris_map[vertex].push(tri_idx)
    end
  end

  tri_indices = Array.new( tris.size )
  vertices = vert_tris_map.keys

  vert_idx = 0
  vert_tris_map.each do | vertex, tri_index_ary |
    tri_index_ary.each do | tri_index |
      tri_indices[tri_index] = Array.new() if( !tri_indices[tri_index] )
      tri_indices[tri_index].push(vert_idx)
    end
    vert_idx += 1
  end

  # modify noamal direction
  tri_idx = 0
  tri_indices.each do | tri_index_ary |
    if ( tri_index_ary.size > 2 )
      tmp_tri = Triangle.new(vertices[tri_index_ary[0]], vertices[tri_index_ary[1]], vertices[tri_index_ary[2]])
      if( tmp_tri.normal.dot(tris[tri_idx].normal) < 0 )
        tri_index_ary.reverse!
      end
    end
    tri_idx += 1
  end

  return TriMesh.new( vertices, tri_indices )
end

Instance Method Details

#==(rhs) ⇒ Object

Input

rhs is TriMesh.

Output

return true if rhs equals myself.



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/tri_mesh.rb', line 188

def ==(rhs)
  return false if rhs == nil
  return false if( !rhs.kind_of?(TriMesh) )
  return false if(@vertices.size != rhs.vertices.size)
  return false if(@tri_indices.size != rhs.tri_indices.size)

  for i in 0..(@vertices.size-1)
    return false if( @vertices[i] != rhs.vertices[i])
  end

  for i in 0..(@tri_indices.size-1)
    return false if( @tri_indices[i] != rhs.tri_indices[i])
  end
  return true
end

#areaObject

Output

return surface area of TriMesh.



232
233
234
235
236
237
238
# File 'lib/tri_mesh.rb', line 232

def area
  area_sum = 0
  triangles.each do | tri |
    area_sum += tri.area
  end
  return area_sum
end

#initialize_copy(original_obj) ⇒ Object



36
37
38
39
40
41
42
43
44
45
# File 'lib/tri_mesh.rb', line 36

def initialize_copy( original_obj )
  @vertices = Array.new(original_obj.vertices.size)
  for i in 0..@vertices.size-1
    @vertices[i] = original_obj.vertices[i].dup
  end
  @tri_indices = Array.new(original_obj.tri_indices.size)
  for i in 0..@tri_indices.size-1
    @tri_indices[i] = original_obj.tri_indices[i].dup
  end
end

#normals_for_each_verticesObject

Output

return normal vector for each vertex as Hash{ Vector3 vertex => Vector3 normal_vector}.



242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/tri_mesh.rb', line 242

def normals_for_each_vertices
  normals_map = Hash.new(nil)
  triangles.each_with_index do | tri, tri_idx |
    tri.vertices.each_with_index do | vertex, ver_idx |
      normals_map[vertex] = Vector3.new() if( !normals_map.key?(vertex) )
      normals_map[vertex] += tri.normal*tri.angle(ver_idx)
    end
  end
  normals_map.each do |vertex, normal|
    normals_map[vertex] = normal.normalize
  end
  return  normals_map
end

#to_sObject



204
205
206
# File 'lib/tri_mesh.rb', line 204

def to_s
  "TriMesh[triangle_count:#{tri_indices.size}, vertex_count:#{vertices.size}]"
end

#triangle(index) ⇒ Object

index is index of triangle.

Output

return new instance of Triangle.



212
213
214
215
216
# File 'lib/tri_mesh.rb', line 212

def triangle(index)
  return nil if( index < 0 || @tri_indices.size <= index )
  tri_index = @tri_indices[index]
  return Triangle.new(vertices[tri_index[0]], vertices[tri_index[1]], vertices[tri_index[2]])
end

#trianglesObject

Output

return Array of Triangle.



220
221
222
223
224
225
226
227
228
# File 'lib/tri_mesh.rb', line 220

def triangles
  tris = Array.new(tri_indices.size)
  i = 0
  tri_indices.each do |tri_index|
    tris[i] =  self.triangle(i)
    i += 1
  end
  return tris
end