Class: GMath3D::Triangle

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

Overview

Triangle represents a three edged finite plane on 3D space.

Instance Attribute Summary collapse

Attributes inherited from Geom

#tolerance

Instance Method Summary collapse

Methods included from BoxAvailable

#box

Methods inherited from Geom

default_tolerance

Constructor Details

#initialize(vertex1 = Vector3.new(), vertex2 = Vector3.new(1,0,0), vertex3 = Vector3.new(0,1,0)) ⇒ Triangle

Input

vertex1, vertex2, vertex3 should be Vector3.

Output

return new instance of Triangle.



17
18
19
20
21
22
23
# File 'lib/triangle.rb', line 17

def initialize(vertex1 = Vector3.new(), vertex2 = Vector3.new(1,0,0), vertex3 = Vector3.new(0,1,0))
  Util3D.check_arg_type(::Vector3, vertex1)
  Util3D.check_arg_type(::Vector3, vertex2)
  Util3D.check_arg_type(::Vector3, vertex3)
  super()
  @vertices = Array.new([vertex1, vertex2, vertex3])
end

Instance Attribute Details

#verticesObject

Returns the value of attribute vertices.



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

def vertices
  @vertices
end

Instance Method Details

#==(rhs) ⇒ Object

Input

rhs is Line.

Output

return true if rhs equals myself.



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

def ==(rhs)
  return false if rhs == nil
  return false if( !rhs.kind_of?(Triangle) )
  return false if(@vertices.size != rhs.vertices.size)
  for i in 0..@vertices.size-1
    return false if(@vertices[i] != rhs.vertices[i])
  end
  return true
end

#angle(vertex_index) ⇒ Object

Input

vertex_index should be 0..2.

Output

return angle as Numeric(radian).



97
98
99
100
101
102
103
104
105
# File 'lib/triangle.rb', line 97

def angle( vertex_index )
  return nil if(vertex_index < 0 || vertex_index > 2)
  vert1 = self.vertices[vertex_index]
  vert2 = self.vertices[(vertex_index+1)%3]
  vert3 = self.vertices[(vertex_index+2)%3]
  vec1 = vert2 - vert1
  vec2 = vert3 - vert1
  vec1.angle(vec2)
end

#areaObject

Output

return area as Numeric.



72
73
74
75
76
77
# File 'lib/triangle.rb', line 72

def area
  vec1 = vertices[1] - vertices[0]
  vec2 = vertices[2] - vertices[0]
  outer_product = vec1.cross(vec2)
  return outer_product.length / 2.0
end

#barycentric_coordinate(check_point) ⇒ Object

Input

check_point should be Vector3.

Output

return barycentric_coordinate on check_point as three element Array of Numeric.



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/triangle.rb', line 117

def barycentric_coordinate( check_point )
  Util3D.check_arg_type(::Vector3, check_point)

  v0 = @vertices[0]
  v1 = @vertices[1]
  v2 = @vertices[2]

  d1 = v1 - v0
  d2 = v2 - v1
  n = d1.cross(d2);
  if((n.x).abs >= (n.y).abs && (n.x).abs >= (n.z).abs)
    uu1 = v0.y - v2.y;
    uu2 = v1.y - v2.y;
    uu3 = check_point.y  - v0.y;
    uu4 = check_point.y  - v2.y;
    vv1 = v0.z - v2.z;
    vv2 = v1.z - v2.z;
    vv3 = check_point.z  - v0.z;
    vv4 = check_point.z  - v2.z;
  elsif((n.y).abs >= (n.z).abs)
    uu1 = v0.z - v2.z;
    uu2 = v1.z - v2.z;
    uu3 = check_point.z  - v0.z;
    uu4 = check_point.z  - v2.z;
    vv1 = v0.x - v2.x;
    vv2 = v1.x - v2.x;
    vv3 = check_point.x  - v0.x;
    vv4 = check_point.x  - v2.x;
  else
    uu1 = v0.x - v2.x;
    uu2 = v1.x - v2.x;
    uu3 = check_point.x  - v0.x;
    uu4 = check_point.x  - v2.x;
    vv1 = v0.y - v2.y;
    vv2 = v1.y - v2.y;
    vv3 = check_point.y  - v0.y;
    vv4 = check_point.y  - v2.y;
  end

  denom = vv1 * uu2 - vv2* uu1
  if(denom == 0.0)
	return nil
  end
  b = Array.new(3)
  oneOverDenom = 1.0 / denom ;
  b[0] = (vv4*uu2 - vv2*uu4) * oneOverDenom;
  b[1] = (vv1*uu3 - vv3*uu1) * oneOverDenom;
  b[2] = 1.0 - b[0] - b[1];
  return b;
end

#centerObject

Output

return center point as Vector3.



81
82
83
# File 'lib/triangle.rb', line 81

def center
  return vertices.avg
end

#contains?(check_point) ⇒ Boolean

Input

check_point shold be Vector3.

Output

return true if triangle contains check_point.

Returns:

  • (Boolean)


195
196
197
198
199
200
201
202
203
204
205
# File 'lib/triangle.rb', line 195

def contains?( check_point )
  Util3D.check_arg_type(Vector3, check_point )
  plane = Plane.new( vertices[0], self.normal)
  distance, projected_point = plane.distance(check_point)
  return false if( distance > self.tolerance )
  g_coord = self.barycentric_coordinate(check_point)
  g_coord.each do |item|
    return false if( item < 0 or 1 < item)
  end
  return true
end

#distance(target) ⇒ Object

Input

target shold be Vector3 or Line or Plane.

Output
In case target is Vector3

return “distance, point on triangle” as [Numeric, Vector3].

In case target is Line

return “distance, point on tirangle, point on line, parameter on line” as [Numeric, Vector3, Vector3, Numeric].

In case target is Plane

return “distance, intersect_line(or closet edge), point_on_triangle, point_on_plane” as [Numeric, Vector3, Vector3, Vector3].



177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/triangle.rb', line 177

def distance(target)
  # with Point
  if(target.kind_of?(Vector3))
    return distance_to_point(target)
  elsif(target.kind_of?(Line))
  #with Line
    return distance_to_line(target)
  elsif(target.kind_of?(Plane))
  #with Plane
    return distance_to_plane(target)
  end
  Util3D.raise_argurment_error(target)
end

#edgesObject

Output

return edges as three element Array of Vector3.



62
63
64
65
66
67
68
# File 'lib/triangle.rb', line 62

def edges
  return_edges = Array.new(3)
  return_edges[0] = FiniteLine.new(self.vertices[0], self.vertices[1])
  return_edges[1] = FiniteLine.new(self.vertices[1], self.vertices[2])
  return_edges[2] = FiniteLine.new(self.vertices[2], self.vertices[0])
  return return_edges
end

#initialize_copy(original_obj) ⇒ Object



25
26
27
28
29
30
# File 'lib/triangle.rb', line 25

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
end

#normalObject

Output

return normal vector as Vector3.



87
88
89
90
91
# File 'lib/triangle.rb', line 87

def normal
  vec1 = self.vertices[1] - self.vertices[0]
  vec2 = self.vertices[2] - self.vertices[0]
  return (vec1.cross(vec2).normalize)
end

#point(parameter) ⇒ Object

Input

parameter should be three element Array of Numeric.

Output

return point on triangle at parameter position as Vector3.



54
55
56
57
58
# File 'lib/triangle.rb', line 54

def point( parameter )
  Util3D.check_arg_type(::Array, parameter )
  # TODO Argument check
  return self.vertices[0]*parameter[0] + self.vertices[1]*parameter[1] + self.vertices[2]*parameter[2]
end

#reverseObject

Output

return normal vector reversed triangle



109
110
111
# File 'lib/triangle.rb', line 109

def reverse
  return Triangle.new(@vertices[0], @vertices[2], @vertices[1])
end

#to_sObject



46
47
48
# File 'lib/triangle.rb', line 46

def to_s
  "Triangle[#{@vertices[0].to_element_s}, #{@vertices[1].to_element_s}, #{@vertices[2].to_element_s}]"
end