gmath3D 0.2.3 → 0.2.4

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/Gemfile.lock CHANGED
@@ -6,7 +6,7 @@ GEM
6
6
  bundler (~> 1.0)
7
7
  git (>= 1.2.5)
8
8
  rake
9
- rake (0.9.2)
9
+ rake (0.9.2.2)
10
10
 
11
11
  PLATFORMS
12
12
  ruby
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.3
1
+ 0.2.4
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.3"
8
+ s.version = "0.2.4"
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-11-03}
12
+ s.date = %q{2011-11-26}
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 = [
@@ -27,11 +27,11 @@ Gem::Specification.new do |s|
27
27
  "gmath3D.gemspec",
28
28
  "lib/box.rb",
29
29
  "lib/ellipse.rb",
30
+ "lib/ext.rb",
30
31
  "lib/finite_line.rb",
31
32
  "lib/geom.rb",
32
33
  "lib/gmath3D.rb",
33
34
  "lib/line.rb",
34
- "lib/matrix_util.rb",
35
35
  "lib/plane.rb",
36
36
  "lib/polyline.rb",
37
37
  "lib/quat.rb",
data/lib/box.rb CHANGED
@@ -5,7 +5,6 @@ module GMath3D
5
5
  # Box represents an axitially aligned box on 3D space.
6
6
  #
7
7
  class Box < Geom
8
- public
9
8
  attr_reader :min_point
10
9
  attr_reader :max_point
11
10
 
@@ -15,8 +14,8 @@ public
15
14
  # [Output]
16
15
  # return new instance of Box.
17
16
  def initialize(point1 = Vector3.new(0,0,0), point2 = Vector3.new(1,1,1))
18
- Util.check_arg_type(Vector3, point1)
19
- Util.check_arg_type(Vector3, point2)
17
+ Util3D.check_arg_type(Vector3, point1)
18
+ Util3D.check_arg_type(Vector3, point2)
20
19
  super()
21
20
  @min_point = Vector3.new();
22
21
  @max_point = Vector3.new();
@@ -75,6 +74,42 @@ public
75
74
  return width*height*depth
76
75
  end
77
76
 
77
+ # [Output]
78
+ # return all vertices of Box.
79
+ def vertices
80
+ verts = Array.new(8)
81
+ length_ary = self.length
82
+ verts[0] = @min_point.clone
83
+ verts[1] = @min_point + Vector3.new(length_ary[0], 0, 0 )
84
+ verts[2] = @min_point + Vector3.new(length_ary[0], length_ary[1], 0 )
85
+ verts[3] = @min_point + Vector3.new( 0, length_ary[1], 0 )
86
+ verts[4] = @min_point + Vector3.new( 0, 0, length_ary[2])
87
+ verts[5] = @min_point + Vector3.new(length_ary[0], 0, length_ary[2])
88
+ verts[6] = @min_point + Vector3.new(length_ary[0], length_ary[1], length_ary[2])
89
+ verts[7] = @min_point + Vector3.new( 0, length_ary[1], length_ary[2])
90
+ return verts
91
+ end
92
+
93
+ # [input]
94
+ # _vec_ should be Vector3.
95
+ # [Output]
96
+ # return translated box as Box.
97
+ def translate(vec)
98
+ return Box.new(min_point + vec, max_point + vec)
99
+ end
100
+
101
+ # [input]
102
+ # _quat_ should be Quat.
103
+ # [Output]
104
+ # return rotated box as Box.
105
+ # since Box is AABB, returned box might be bigger than original one.
106
+ def rotate(quat)
107
+ rot_matrix = Matrix.from_quat(quat)
108
+ verts = self.vertices
109
+ verts = verts.collect {|item| rot_matrix*item}
110
+ return Box.from_points(verts)
111
+ end
112
+
78
113
  private
79
114
  def equals_inner(rhs)
80
115
  return false if( !rhs.kind_of?(Box) )
@@ -103,7 +138,7 @@ private
103
138
  end
104
139
  return added_box
105
140
  end
106
- Util.raise_argurment_error(rhs)
141
+ Util3D.raise_argurment_error(rhs)
107
142
  end
108
143
  end
109
144
  end
data/lib/ext.rb ADDED
@@ -0,0 +1,82 @@
1
+ require 'gmath3D'
2
+ require 'matrix'
3
+
4
+ module GMath3D
5
+ class ::Matrix
6
+ def self.from_axis(axis, angle)
7
+ Util3D::check_arg_type(Vector3, axis)
8
+ Util3D::check_arg_type(Numeric, angle)
9
+
10
+ return Matrix[
11
+ [axis.x*axis.x*(1 - Math.cos(angle)) + Math.cos(angle),
12
+ axis.x*axis.y*(1 - Math.cos(angle)) + axis.z*Math.sin(angle),
13
+ axis.x*axis.z*(1 - Math.cos(angle)) - axis.y*Math.sin(angle)],
14
+ [axis.x*axis.y*(1 - Math.cos(angle)) - axis.z*Math.sin(angle),
15
+ axis.y*axis.y*(1 - Math.cos(angle)) + Math.cos(angle),
16
+ axis.y*axis.z*(1 - Math.cos(angle)) + axis.x*Math.sin(angle)],
17
+ [axis.x*axis.z*(1 - Math.cos(angle)) + axis.y*Math.sin(angle),
18
+ axis.y*axis.z*(1 - Math.cos(angle)) - axis.x*Math.sin(angle),
19
+ axis.z*axis.z*(1 - Math.cos(angle)) + Math.cos(angle)]]
20
+ end
21
+
22
+ def self.from_quat(quat)
23
+ Util3D::check_arg_type(Quat, quat)
24
+ qw = quat.w
25
+ qx = quat.x
26
+ qy = quat.y
27
+ qz = quat.z
28
+
29
+ x2 = 2.0 * qx * qx;
30
+ y2 = 2.0 * qy * qy;
31
+ z2 = 2.0 * qz * qz;
32
+ xy = 2.0 * qx * qy;
33
+ yz = 2.0 * qy * qz;
34
+ zx = 2.0 * qz * qx;
35
+ wx = 2.0 * qw * qx;
36
+ wy = 2.0 * qw * qy;
37
+ wz = 2.0 * qw * qz;
38
+
39
+ return Matrix[
40
+ [ 1.0 - y2 - z2, xy + wz, zx - wy],
41
+ [ xy - wz, 1.0 - z2 - x2, yz + wx],
42
+ [ zx + wy, yz - wx, 1.0 - x2 - y2]]
43
+ end
44
+
45
+ alias_method :multi_inner, :* # hold original multiply processing
46
+ def multi_new(rhs)
47
+ if(rhs.kind_of?(Vector3))
48
+ ans = self.multi_inner(rhs.to_column_vector)
49
+ return Vector3.new(ans[0,0], ans[1,0], ans[2,0])
50
+ end
51
+ multi_inner(rhs)
52
+ end
53
+ alias_method :*, :multi_new # overwrite new multiply processing
54
+ end
55
+
56
+ class ::Array
57
+ def sum
58
+ s, n = self.sum_with_number
59
+ return s
60
+ end
61
+ def avg
62
+ s, n = self.sum_with_number
63
+ return s / n
64
+ end
65
+
66
+ def sum_with_number
67
+ return nil, 0 if(self.size <= 0)
68
+ s = nil
69
+ n = 0
70
+ self.each do |v|
71
+ next if v.nil?
72
+ if(s==nil)
73
+ s = v
74
+ else
75
+ s += v
76
+ end
77
+ n += 1
78
+ end
79
+ return s, n
80
+ end
81
+ end
82
+ end
data/lib/finite_line.rb CHANGED
@@ -16,8 +16,8 @@ public
16
16
  # [Output]
17
17
  # return new instance as FiniteLine
18
18
  def initialize(start_point = Vector3.new(0,0,0), end_point = Vector3.new(1,0,0))
19
- Util.check_arg_type(Vector3, start_point)
20
- Util.check_arg_type(Vector3, end_point)
19
+ Util3D.check_arg_type(Vector3, start_point)
20
+ Util3D.check_arg_type(Vector3, end_point)
21
21
  super()
22
22
  @start_point = start_point
23
23
  @end_point = end_point
@@ -105,12 +105,12 @@ public
105
105
  elsif(target.kind_of?(FiniteLine))
106
106
  return distance_to_finite_line(target)
107
107
  end
108
- Util.raise_argurment_error(target)
108
+ Util3D.raise_argurment_error(target)
109
109
  end
110
110
 
111
111
  def self.ary_distanc_to_point(finite_lines, target_point)
112
- Util.check_arg_type(::Array, finite_lines)
113
- Util.check_arg_type(Vector3, target_point)
112
+ Util3D.check_arg_type(::Array, finite_lines)
113
+ Util3D.check_arg_type(Vector3, target_point)
114
114
  distance_ary = Array.new(0)
115
115
  points_ary = Array.new(0)
116
116
  finite_lines.each do | item |
@@ -124,8 +124,8 @@ public
124
124
  end
125
125
 
126
126
  def self.ary_distance_to_line(finite_lines, target_line)
127
- Util.check_arg_type(::Array, finite_lines)
128
- Util.check_arg_type(Line, target_line)
127
+ Util3D.check_arg_type(::Array, finite_lines)
128
+ Util3D.check_arg_type(Line, target_line)
129
129
  distance_ary = Array.new(0)
130
130
  point_on_target_ary = Array.new(0)
131
131
  point_on_finite_line_ary = Array.new(0)
data/lib/gmath3D.rb CHANGED
@@ -1,10 +1,12 @@
1
1
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
 
3
3
  require 'util'
4
+ require 'ext'
5
+
4
6
  require 'geom'
5
- require 'vector3'
6
7
  require 'quat'
7
- require 'matrix_util'
8
+
9
+ require 'vector3'
8
10
 
9
11
  require 'line'
10
12
  require 'finite_line'
data/lib/line.rb CHANGED
@@ -18,8 +18,8 @@ module GMath3D
18
18
  # [Output]
19
19
  # return new instance of Line.
20
20
  def initialize(point = Vector3.new(0.0,0.0,0.0), direction = Vector3.new(1.0,0.0,0.0))
21
- Util.check_arg_type(Vector3, point)
22
- Util.check_arg_type(Vector3, direction)
21
+ Util3D.check_arg_type(Vector3, point)
22
+ Util3D.check_arg_type(Vector3, direction)
23
23
  super()
24
24
  @base_point = point
25
25
  @direction = direction
@@ -47,7 +47,7 @@ module GMath3D
47
47
  # [Output]
48
48
  # return a point on line at input parameter position as Vector3
49
49
  def point(parameter)
50
- Util.check_arg_type(::Numeric, parameter)
50
+ Util3D.check_arg_type(::Numeric, parameter)
51
51
  @base_point + @direction*parameter
52
52
  end
53
53
 
@@ -69,7 +69,7 @@ module GMath3D
69
69
  elsif(target.kind_of?(Line))
70
70
  return distance_to_line(target)
71
71
  end
72
- Util.raise_argurment_error(target)
72
+ Util3D.raise_argurment_error(target)
73
73
  end
74
74
 
75
75
  private
data/lib/plane.rb CHANGED
@@ -5,7 +5,6 @@ module GMath3D
5
5
  # Plane represents a infinite plane on 3D space.
6
6
  #
7
7
  class Plane < Geom
8
- public
9
8
  attr_accessor:base_point
10
9
  attr_accessor:normal
11
10
 
@@ -14,8 +13,8 @@ public
14
13
  # [Output]
15
14
  # returns new instance of Plane.
16
15
  def initialize(base_point = Vector3.new(), normal = Vector3.new(0,0,1))
17
- Util.check_arg_type(::Vector3, normal)
18
- Util.check_arg_type(::Vector3, base_point)
16
+ Util3D.check_arg_type(::Vector3, normal)
17
+ Util3D.check_arg_type(::Vector3, base_point)
19
18
  super()
20
19
  @base_point = base_point
21
20
  @normal = normal.normalize()
@@ -70,7 +69,7 @@ public
70
69
  elsif(target.kind_of?(Plane))
71
70
  return distance_to_plane(target)
72
71
  end
73
- Util.raise_argurment_error(target)
72
+ Util3D.raise_argurment_error(target)
74
73
  end
75
74
 
76
75
  # [Input]
@@ -78,7 +77,7 @@ public
78
77
  # [Output]
79
78
  # retrun projected point on plane as Vector3.
80
79
  def project( target_point )
81
- Util.check_arg_type(::Vector3, target_point)
80
+ Util3D.check_arg_type(::Vector3, target_point)
82
81
  distance, closest_point = self.distance( target_point )
83
82
  return closest_point
84
83
  end
data/lib/polyline.rb CHANGED
@@ -16,7 +16,7 @@ module GMath3D
16
16
  # [Output]
17
17
  # return new instance of Polyline.
18
18
  def initialize(vertices = [], is_open = true)
19
- Util.check_arg_type(Array, vertices)
19
+ Util3D.check_arg_type(Array, vertices)
20
20
  super()
21
21
  @vertices = vertices
22
22
  @is_open = is_open
data/lib/quat.rb CHANGED
@@ -16,10 +16,10 @@ public
16
16
  # [Output]
17
17
  # return new instance of Quat.
18
18
  def initialize(x=0.0,y=0.0,z=0.0,w=0.0)
19
- Util.check_arg_type(Numeric, x)
20
- Util.check_arg_type(Numeric, y)
21
- Util.check_arg_type(Numeric, z)
22
- Util.check_arg_type(Numeric, w)
19
+ Util3D.check_arg_type(Numeric, x)
20
+ Util3D.check_arg_type(Numeric, y)
21
+ Util3D.check_arg_type(Numeric, z)
22
+ Util3D.check_arg_type(Numeric, w)
23
23
  super()
24
24
  @x = x
25
25
  @y = y
@@ -32,8 +32,8 @@ public
32
32
  # [Output]
33
33
  # return new instance of Quat.
34
34
  def self.from_axis(axis, angle)
35
- Util.check_arg_type(Vector3, axis)
36
- Util.check_arg_type(Numeric, angle)
35
+ Util3D.check_arg_type(Vector3, axis)
36
+ Util3D.check_arg_type(Numeric, angle)
37
37
  s = Math.sin(0.5*angle)
38
38
  x = s * axis.x
39
39
  y = s * axis.y
@@ -134,7 +134,7 @@ public
134
134
  # [Output]
135
135
  # return added result as Quat.
136
136
  def +(rhs)
137
- Util.check_arg_type(Quat, rhs)
137
+ Util3D.check_arg_type(Quat, rhs)
138
138
  t1 = Vector3.new(self.x, self.y, self.z)
139
139
  t2 = Vector3.new(rhs.x, rhs.y, rhs.z)
140
140
  dot = t1.dot(t2)
@@ -154,7 +154,7 @@ public
154
154
  # [Output]
155
155
  # return (outer products) multiplyed result as Quat.
156
156
  def *(rhs)
157
- Util.check_arg_type(Quat, rhs)
157
+ Util3D.check_arg_type(Quat, rhs)
158
158
 
159
159
  pw = self.w; px = self.x; py = self.y; pz = self.z;
160
160
  qw = rhs.w ; qx = rhs.x ; qy = rhs.y ; qz = rhs.z;
data/lib/rectangle.rb CHANGED
@@ -20,9 +20,9 @@ public
20
20
  # [Output]
21
21
  # return new instance of Rectangle.
22
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
- Util.check_arg_type(::Vector3, base_point_arg)
24
- Util.check_arg_type(::Vector3, u_vector_arg)
25
- Util.check_arg_type(::Vector3, v_vector_arg)
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
26
  super()
27
27
  self.base_point = base_point_arg
28
28
  self.u_vector = u_vector_arg
@@ -57,8 +57,8 @@ public
57
57
  # [Output]
58
58
  # return point on rectangle as Vector3.
59
59
  def point(u, v)
60
- Util.check_arg_type(::Numeric, u)
61
- Util.check_arg_type(::Numeric, v)
60
+ Util3D.check_arg_type(::Numeric, u)
61
+ Util3D.check_arg_type(::Numeric, v)
62
62
  return base_point + u_vector*u + v_vector*v
63
63
  end
64
64
 
@@ -113,7 +113,7 @@ public
113
113
  # [Output]
114
114
  # return u, v parametes on check_point as [Numeric, Numeric].
115
115
  def uv_parameter(check_point)
116
- Util.check_arg_type(::Vector3, check_point)
116
+ Util3D.check_arg_type(::Vector3, check_point)
117
117
  mat = Matrix[[u_vector.x, u_vector.y, u_vector.z],
118
118
  [v_vector.x, v_vector.y, v_vector.z],
119
119
  [normal.x, normal.y, normal.z]]
@@ -134,7 +134,7 @@ public
134
134
  #with Line
135
135
  # return distance_to_line(target)
136
136
  end
137
- Util.raise_argurment_error(target)
137
+ Util3D.raise_argurment_error(target)
138
138
  end
139
139
 
140
140
  private
data/lib/tri_mesh.rb CHANGED
@@ -17,15 +17,15 @@ module GMath3D
17
17
  # return new instance of TriMesh.
18
18
  def initialize(vertices, tri_indices)
19
19
  # check arg
20
- Util.check_arg_type(Array, vertices)
21
- Util.check_arg_type(Array, tri_indices)
20
+ Util3D.check_arg_type(Array, vertices)
21
+ Util3D.check_arg_type(Array, tri_indices)
22
22
  vertices.each do |item|
23
- Util.check_arg_type(Vector3, item)
23
+ Util3D.check_arg_type(Vector3, item)
24
24
  end
25
25
  tri_indices.each do |tri_index|
26
- Util.check_arg_type(Array, tri_index)
26
+ Util3D.check_arg_type(Array, tri_index)
27
27
  tri_index.each do |item|
28
- Util.check_arg_type(Integer, item)
28
+ Util3D.check_arg_type(Integer, item)
29
29
  end
30
30
  end
31
31
  super()
@@ -49,7 +49,7 @@ module GMath3D
49
49
  # [Output]
50
50
  # return new instance of TriMesh.
51
51
  def self.from_box(box)
52
- Util.check_arg_type(Box, box)
52
+ Util3D.check_arg_type(Box, box)
53
53
  width, height, depth = box.length()
54
54
  vertices = Array.new(8)
55
55
  vertices[0] = box.min_point
@@ -82,7 +82,7 @@ module GMath3D
82
82
  # [Output]
83
83
  # return new instance of TriMesh.
84
84
  def self.from_rectangle(rect)
85
- Util.check_arg_type(Rectangle, rect)
85
+ Util3D.check_arg_type(Rectangle, rect)
86
86
  return TriMesh.new(rect.vertices, [[0,1,3], [1,2,3]])
87
87
  end
88
88
 
@@ -91,19 +91,18 @@ module GMath3D
91
91
  # [Output]
92
92
  # return new instance of TriMesh
93
93
  def self.from_triangles(tris)
94
- Util.check_arg_type(Array, tris)
94
+ Util3D.check_arg_type(Array, tris)
95
95
  tris.each do | item |
96
- Util.check_arg_type(Triangle, item)
96
+ Util3D.check_arg_type(Triangle, item)
97
97
  end
98
98
 
99
99
  tri_idx = 0
100
100
  vert_tris_map = Hash.new(nil)
101
- tris.each do | triangle |
101
+ tris.each_with_index do | triangle, tri_idx |
102
102
  triangle.vertices.each do | vertex |
103
103
  vert_tris_map[vertex] = Array.new() if( !vert_tris_map.key?(vertex) )
104
104
  vert_tris_map[vertex] = vert_tris_map[vertex].push(tri_idx)
105
105
  end
106
- tri_idx += 1
107
106
  end
108
107
 
109
108
  tri_indices = Array.new( tris.size )
@@ -237,6 +236,23 @@ module GMath3D
237
236
  end
238
237
  return area_sum
239
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
+
240
256
  end
241
257
  end
242
258
 
data/lib/triangle.rb CHANGED
@@ -15,9 +15,9 @@ public
15
15
  # [Output]
16
16
  # return new instance of Triangle.
17
17
  def initialize(vertex1 = Vector3.new(), vertex2 = Vector3.new(1,0,0), vertex3 = Vector3.new(0,1,0))
18
- Util.check_arg_type(::Vector3, vertex1)
19
- Util.check_arg_type(::Vector3, vertex2)
20
- Util.check_arg_type(::Vector3, vertex3)
18
+ Util3D.check_arg_type(::Vector3, vertex1)
19
+ Util3D.check_arg_type(::Vector3, vertex2)
20
+ Util3D.check_arg_type(::Vector3, vertex3)
21
21
  super()
22
22
  @vertices = Array.new([vertex1, vertex2, vertex3])
23
23
  end
@@ -52,7 +52,7 @@ public
52
52
  # [Output]
53
53
  # return point on triangle at parameter position as Vector3.
54
54
  def point( parameter )
55
- Util.check_arg_type(::Array, parameter )
55
+ Util3D.check_arg_type(::Array, parameter )
56
56
  # TODO Argument check
57
57
  return self.vertices[0]*parameter[0] + self.vertices[1]*parameter[1] + self.vertices[2]*parameter[2]
58
58
  end
@@ -90,9 +90,23 @@ public
90
90
  return (vec1.cross(vec2).normalize)
91
91
  end
92
92
 
93
+ # [Input]
94
+ # _vertex_index_ should be 0..2.
95
+ # [Output]
96
+ # return angle as Numeric(radian).
97
+ def angle( vertex_index )
98
+ return nil if(vertex_index < 0 || vertex_index > 2)
99
+ vert1 = self.vertices[vertex_index]
100
+ vert2 = self.vertices[(vertex_index+1)%3]
101
+ vert3 = self.vertices[(vertex_index+2)%3]
102
+ vec1 = vert2 - vert1
103
+ vec2 = vert3 - vert1
104
+ vec1.angle(vec2)
105
+ end
106
+
93
107
  # [Output]
94
108
  # return normal vector reversed triangle
95
- def reverse()
109
+ def reverse
96
110
  return Triangle.new(@vertices[0], @vertices[2], @vertices[1])
97
111
  end
98
112
 
@@ -101,7 +115,7 @@ public
101
115
  # [Output]
102
116
  # return barycentric_coordinate on check_point as three element Array of Numeric.
103
117
  def barycentric_coordinate( check_point )
104
- Util.check_arg_type(::Vector3, check_point)
118
+ Util3D.check_arg_type(::Vector3, check_point)
105
119
 
106
120
  v0 = @vertices[0]
107
121
  v1 = @vertices[1]
@@ -171,7 +185,7 @@ public
171
185
  #with Plane
172
186
  return distance_to_plane(target)
173
187
  end
174
- Util.raise_argurment_error(target)
188
+ Util3D.raise_argurment_error(target)
175
189
  end
176
190
 
177
191
  # [Input]
@@ -179,7 +193,7 @@ public
179
193
  # [Output]
180
194
  # return true if triangle contains _check_point_.
181
195
  def contains?( check_point )
182
- Util.check_arg_type(Vector3, check_point )
196
+ Util3D.check_arg_type(Vector3, check_point )
183
197
  plane = Plane.new( vertices[0], self.normal)
184
198
  distance, projected_point = plane.distance(check_point)
185
199
  return false if( distance > self.tolerance )
data/lib/util.rb CHANGED
@@ -1,16 +1,16 @@
1
- module GMath3D
2
- class Util
3
- def self.check_arg_type(type, instance)
4
- unless(instance.kind_of?(type))
5
- raise(ArgumentError::new("type mismatch: #{instance.class} for #{type}"))
6
- end
1
+ module Util3D
2
+ def self.check_arg_type(type, instance)
3
+ unless(instance.kind_of?(type))
4
+ raise(ArgumentError::new("type mismatch: #{instance.class} for #{type}"))
7
5
  end
6
+ end
8
7
 
9
- def self.raise_argurment_error(instance)
10
- raise(ArgumentError::new("type mismatch: #{instance.class}"))
11
- end
8
+ def self.raise_argurment_error(instance)
9
+ raise(ArgumentError::new("type mismatch: #{instance.class}"))
12
10
  end
11
+ end
13
12
 
13
+ module GMath3D
14
14
  # Including 'vertices' methodshould be implimented that gets geometry vertices as Array of Vector3.
15
15
  module BoxAvailable
16
16
  # [Output]
@@ -21,30 +21,3 @@ module GMath3D
21
21
  end
22
22
  end
23
23
 
24
- class Array
25
- public
26
- def sum
27
- s, n = self.sum_with_number
28
- return s
29
- end
30
- def avg
31
- s, n = self.sum_with_number
32
- return s / n
33
- end
34
-
35
- def sum_with_number
36
- return nil, 0 if(self.size <= 0)
37
- s = nil
38
- n = 0
39
- self.each do |v|
40
- next if v.nil?
41
- if(s==nil)
42
- s = v
43
- else
44
- s += v
45
- end
46
- n += 1
47
- end
48
- return s, n
49
- end
50
- end
data/lib/vector3.rb CHANGED
@@ -6,7 +6,6 @@ module GMath3D
6
6
  # Vector3 represents a point or a vector on 3D space.
7
7
  #
8
8
  class Vector3 < Geom
9
- public
10
9
  attr_accessor :x
11
10
  attr_accessor :y
12
11
  attr_accessor :z
@@ -16,9 +15,9 @@ public
16
15
  # [Output]
17
16
  # return new instance as Vector3.
18
17
  def initialize(x=0.0,y=0.0,z=0.0)
19
- Util.check_arg_type(Numeric, x)
20
- Util.check_arg_type(Numeric, y)
21
- Util.check_arg_type(Numeric, z)
18
+ Util3D.check_arg_type(Numeric, x)
19
+ Util3D.check_arg_type(Numeric, y)
20
+ Util3D.check_arg_type(Numeric, z)
22
21
  super()
23
22
  @x = x
24
23
  @y = y
@@ -93,7 +92,7 @@ public
93
92
  # [Output]
94
93
  # return inner product as Numeric
95
94
  def dot(rhs)
96
- Util.check_arg_type(Vector3, rhs)
95
+ Util3D.check_arg_type(Vector3, rhs)
97
96
  self.x*rhs.x + self.y*rhs.y + self.z*rhs.z
98
97
  end
99
98
 
@@ -102,7 +101,7 @@ public
102
101
  # [Output]
103
102
  # return cross product as Vector3.
104
103
  def cross(rhs)
105
- Util.check_arg_type(Vector3, rhs)
104
+ Util3D.check_arg_type(Vector3, rhs)
106
105
  Vector3.new(
107
106
  self.y*rhs.z - self.z*rhs.y,
108
107
  self.z*rhs.x - self.x*rhs.z,
@@ -137,7 +136,7 @@ public
137
136
  # [Output]
138
137
  # return distance between two points as Numeric.
139
138
  def distance(rhs)
140
- Util.check_arg_type(Vector3, rhs)
139
+ Util3D.check_arg_type(Vector3, rhs)
141
140
  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))
142
141
  end
143
142
 
@@ -146,7 +145,7 @@ public
146
145
  # [Output]
147
146
  # return two vectors angle as Numeric (rad).
148
147
  def angle(rhs)
149
- Util.check_arg_type(Vector3, rhs)
148
+ Util3D.check_arg_type(Vector3, rhs)
150
149
  vec1Length = self.length ;
151
150
  vec2Length = rhs.length ;
152
151
  return 0.0 if(vec1Length*vec2Length < self.tolerance )
@@ -165,7 +164,7 @@ public
165
164
  # [Output]
166
165
  # return true if myself and rhs is parallel as boolean
167
166
  def parallel?(rhs)
168
- Util.check_arg_type(Vector3, rhs)
167
+ Util3D.check_arg_type(Vector3, rhs)
169
168
  return false if(self.length < self.tolerance or rhs.length < rhs.tolerance)
170
169
  return false if(self.cross(rhs).length > self.tolerance)
171
170
  return true
@@ -176,7 +175,7 @@ public
176
175
  # [Output]
177
176
  # return true if myself and rhs have same direction as boolean.
178
177
  def same_direction?(rhs)
179
- Util.check_arg_type(Vector3, rhs)
178
+ Util3D.check_arg_type(Vector3, rhs)
180
179
  return false if(!parallel?(rhs))
181
180
  return false if(self.dot(rhs) < self.tolerance)
182
181
  return true
@@ -188,7 +187,7 @@ public
188
187
  # [Output]
189
188
  # return projected result as Vector3.
190
189
  def project_to(rhs)
191
- Util.check_arg_type(Vector3, rhs)
190
+ Util3D.check_arg_type(Vector3, rhs)
192
191
  return Vector3.new, 0.0 if( rhs.length < rhs.tolerance )
193
192
  parameter = self.dot( rhs ) / ( rhs.x * rhs.x + rhs.y * rhs.y + rhs.z * rhs.z ).to_f
194
193
  return rhs*parameter, parameter
@@ -208,19 +207,19 @@ public
208
207
  true
209
208
  end
210
209
  def add(rhs)
211
- Util.check_arg_type(Vector3, rhs)
210
+ Util3D.check_arg_type(Vector3, rhs)
212
211
  Vector3.new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z)
213
212
  end
214
213
  def subtract(rhs)
215
- Util.check_arg_type(Vector3, rhs)
214
+ Util3D.check_arg_type(Vector3, rhs)
216
215
  Vector3.new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z)
217
216
  end
218
217
  def multiply(rhs)
219
- Util.check_arg_type(::Numeric, rhs)
218
+ Util3D.check_arg_type(::Numeric, rhs)
220
219
  Vector3.new(self.x * rhs, self.y * rhs, self.z * rhs)
221
220
  end
222
221
  def divide(rhs)
223
- Util.check_arg_type(::Numeric, rhs)
222
+ Util3D.check_arg_type(::Numeric, rhs)
224
223
  Vector3.new(self.x.to_f / rhs, self.y / rhs.to_f, self.z / rhs.to_f)
225
224
  end
226
225
  end
data/test/test_box.rb CHANGED
@@ -116,4 +116,52 @@ class BoxTestCase < MiniTest::Unit::TestCase
116
116
  assert_in_delta( 1.0, @box_default.volume, @box_default.tolerance )
117
117
  assert_in_delta( 112.5, @box.volume, @box.tolerance )
118
118
  end
119
+
120
+ def test_vertices
121
+ verts = @box_default.vertices
122
+ assert(verts.include?(Vector3.new(0,0,0)))
123
+ assert(verts.include?(Vector3.new(1,0,0)))
124
+ assert(verts.include?(Vector3.new(1,1,0)))
125
+ assert(verts.include?(Vector3.new(0,1,0)))
126
+ assert(verts.include?(Vector3.new(0,0,1)))
127
+ assert(verts.include?(Vector3.new(1,0,1)))
128
+ assert(verts.include?(Vector3.new(1,1,1)))
129
+ assert(verts.include?(Vector3.new(0,1,1)))
130
+
131
+ verts = @box.vertices #.new(-3,2,5), Vector3.new(2,-2.5, 0))
132
+ assert(verts.include?(Vector3.new(-3, -2.5, 0)))
133
+ assert(verts.include?(Vector3.new( 2, -2.5, 0)))
134
+ assert(verts.include?(Vector3.new( 2, 2.0, 0)))
135
+ assert(verts.include?(Vector3.new(-3, 2.0, 0)))
136
+ assert(verts.include?(Vector3.new(-3, -2.5, 5)))
137
+ assert(verts.include?(Vector3.new( 2, -2.5, 5)))
138
+ assert(verts.include?(Vector3.new( 2, 2.0, 5)))
139
+ assert(verts.include?(Vector3.new(-3, 2.0, 5)))
140
+ end
141
+
142
+ def test_translate
143
+ trans = Vector3.new(1,2.5,-0.5)
144
+ translated = @box_default.translate(trans)
145
+ assert_equal(Box.new(Vector3.new(1,2.5,-0.5), Vector3.new(2,3.5,0.5)), translated)
146
+
147
+ # this procedure is not destructive
148
+ assert_equal(Box.new(Vector3.new(0,0,0), Vector3.new(1,1,1)), @box_default)
149
+ end
150
+
151
+ def test_rotate
152
+ angle_90 = 90.0*Math::PI/180.0
153
+ angle_45 = 45.0*Math::PI/180.0
154
+ rotation1 = Quat.from_axis(Vector3.new(0,0,1), angle_90)
155
+ rotation2 = Quat.from_axis(Vector3.new(0,0,1), angle_45)
156
+ # rotation3 = Quat.from_axis(Vector3.new(1,1,1).normalize, angle_90)
157
+ rotated1 = @box_default.rotate(rotation1)
158
+ rotated2 = @box_default.rotate(rotation2)
159
+ assert_equal(Box.new(Vector3.new(0,-1,0), Vector3.new(1,0,1)), rotated1)
160
+ assert_equal(Box.new(
161
+ Vector3.new(0, -(Math.sqrt(2.0)/2) ,0),
162
+ Vector3.new(Math.sqrt(2.0), (Math.sqrt(2.0)/2) ,1)), rotated2)
163
+
164
+ # this procedure is not destructive
165
+ assert_equal(Box.new(Vector3.new(0,0,0), Vector3.new(1,1,1)), @box_default)
166
+ end
119
167
  end
@@ -173,4 +173,14 @@ class TriMeshTestCase < MiniTest::Unit::TestCase
173
173
  box_mesh = get_box_mesh()
174
174
  assert_equal(94, box_mesh.area)
175
175
  end
176
+
177
+ def test_normals_for_each_vertices
178
+ box = Box.new(Vector3.new(-1,-1,-1), Vector3.new(1,1,1))
179
+ box_mesh = TriMesh.from_box(box)
180
+ result = box_mesh.normals_for_each_vertices
181
+ assert_equal( box_mesh.vertices.size, result.size )
182
+ box_mesh.vertices.each do |vertex|
183
+ assert_equal(vertex.normalize, result[vertex])
184
+ end
185
+ end
176
186
  end
@@ -299,4 +299,20 @@ class TriangleTestCase < MiniTest::Unit::TestCase
299
299
  assert_equal( nil, point_on_triangle )
300
300
  assert_equal( nil, point_on_plane )
301
301
  end
302
+
303
+ def test_angle
304
+ triangle1 = Triangle.new( Vector3.new(0,0,1), Vector3.new(Math.sqrt(3.0),0,1), Vector3.new(0,1,1))
305
+ triangle2 = Triangle.new( Vector3.new(1,0,0), Vector3.new(0,0,1), Vector3.new(1,1,1))
306
+
307
+ assert_equal(nil, triangle1.angle(-1))
308
+ assert_equal(nil, triangle1.angle(3))
309
+
310
+ assert_in_delta(90.0*Math::PI/180.0, triangle1.angle(0), triangle1.tolerance)
311
+ assert_in_delta(30.0*Math::PI/180.0, triangle1.angle(1), triangle1.tolerance)
312
+ assert_in_delta(60.0*Math::PI/180.0, triangle1.angle(2), triangle1.tolerance)
313
+
314
+ assert_in_delta(60.0*Math::PI/180.0, triangle2.angle(0), triangle1.tolerance)
315
+ assert_in_delta(60.0*Math::PI/180.0, triangle2.angle(1), triangle1.tolerance)
316
+ assert_in_delta(60.0*Math::PI/180.0, triangle2.angle(2), triangle1.tolerance)
317
+ end
302
318
  end
data/test/test_util.rb CHANGED
@@ -12,28 +12,28 @@ class UtilTestCase < MiniTest::Unit::TestCase
12
12
  stringInstance = 'string'
13
13
 
14
14
  # no exception raise
15
- Util.check_arg_type(Integer, integerInstance)
16
- Util.check_arg_type(Float, floatInstance)
17
- Util.check_arg_type(String, stringInstance)
15
+ Util3D.check_arg_type(Integer, integerInstance)
16
+ Util3D.check_arg_type(Float, floatInstance)
17
+ Util3D.check_arg_type(String, stringInstance)
18
18
 
19
19
  # exception raise
20
20
  assert_raises ArgumentError do
21
- Util.check_arg_type(Integer, floatInstance)
21
+ Util3D.check_arg_type(Integer, floatInstance)
22
22
  end
23
23
  assert_raises ArgumentError do
24
- Util.check_arg_type(Integer, stringInstance)
24
+ Util3D.check_arg_type(Integer, stringInstance)
25
25
  end
26
26
  assert_raises ArgumentError do
27
- Util.check_arg_type(Float, integerInstance)
27
+ Util3D.check_arg_type(Float, integerInstance)
28
28
  end
29
29
  assert_raises ArgumentError do
30
- Util.check_arg_type(Float, stringInstance)
30
+ Util3D.check_arg_type(Float, stringInstance)
31
31
  end
32
32
  assert_raises ArgumentError do
33
- Util.check_arg_type(String, integerInstance)
33
+ Util3D.check_arg_type(String, integerInstance)
34
34
  end
35
35
  assert_raises ArgumentError do
36
- Util.check_arg_type(String, floatInstance)
36
+ Util3D.check_arg_type(String, floatInstance)
37
37
  end
38
38
  end
39
39
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gmath3D
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,12 +9,12 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-03 00:00:00.000000000 +09:00
12
+ date: 2011-11-26 00:00:00.000000000 +09:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
17
- requirement: &2156037040 !ruby/object:Gem::Requirement
17
+ requirement: &2151937640 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ~>
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: 1.0.0
23
23
  type: :development
24
24
  prerelease: false
25
- version_requirements: *2156037040
25
+ version_requirements: *2151937640
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: jeweler
28
- requirement: &2156035880 !ruby/object:Gem::Requirement
28
+ requirement: &2151936740 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ~>
@@ -33,7 +33,7 @@ dependencies:
33
33
  version: 1.6.4
34
34
  type: :development
35
35
  prerelease: false
36
- version_requirements: *2156035880
36
+ version_requirements: *2151936740
37
37
  description: This library defines 3D geometric elements(point, line, plane etc..).
38
38
  It can get two(or more) elements relation, like distance between two elements.
39
39
  email: toshi0328@gmail.com
@@ -53,11 +53,11 @@ files:
53
53
  - gmath3D.gemspec
54
54
  - lib/box.rb
55
55
  - lib/ellipse.rb
56
+ - lib/ext.rb
56
57
  - lib/finite_line.rb
57
58
  - lib/geom.rb
58
59
  - lib/gmath3D.rb
59
60
  - lib/line.rb
60
- - lib/matrix_util.rb
61
61
  - lib/plane.rb
62
62
  - lib/polyline.rb
63
63
  - lib/quat.rb
@@ -97,7 +97,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
97
97
  version: '0'
98
98
  segments:
99
99
  - 0
100
- hash: 3556461112353261793
100
+ hash: -2832198732220705826
101
101
  required_rubygems_version: !ruby/object:Gem::Requirement
102
102
  none: false
103
103
  requirements:
data/lib/matrix_util.rb DELETED
@@ -1,55 +0,0 @@
1
- require 'gmath3D'
2
- require 'matrix'
3
-
4
-
5
- class Matrix
6
- def self.from_axis(axis, angle)
7
- Util.check_arg_type(Vector3, axis)
8
- Util.check_arg_type(Numeric, angle)
9
-
10
- return Matrix[
11
- [axis.x*axis.x*(1 - Math.cos(angle)) + Math.cos(angle),
12
- axis.x*axis.y*(1 - Math.cos(angle)) + axis.z*Math.sin(angle),
13
- axis.x*axis.z*(1 - Math.cos(angle)) - axis.y*Math.sin(angle)],
14
- [axis.x*axis.y*(1 - Math.cos(angle)) - axis.z*Math.sin(angle),
15
- axis.y*axis.y*(1 - Math.cos(angle)) + Math.cos(angle),
16
- axis.y*axis.z*(1 - Math.cos(angle)) + axis.x*Math.sin(angle)],
17
- [axis.x*axis.z*(1 - Math.cos(angle)) + axis.y*Math.sin(angle),
18
- axis.y*axis.z*(1 - Math.cos(angle)) - axis.x*Math.sin(angle),
19
- axis.z*axis.z*(1 - Math.cos(angle)) + Math.cos(angle)]]
20
- end
21
-
22
- def self.from_quat(quat)
23
- Util.check_arg_type(Quat, quat)
24
- qw = quat.w
25
- qx = quat.x
26
- qy = quat.y
27
- qz = quat.z
28
-
29
- x2 = 2.0 * qx * qx;
30
- y2 = 2.0 * qy * qy;
31
- z2 = 2.0 * qz * qz;
32
- xy = 2.0 * qx * qy;
33
- yz = 2.0 * qy * qz;
34
- zx = 2.0 * qz * qx;
35
- wx = 2.0 * qw * qx;
36
- wy = 2.0 * qw * qy;
37
- wz = 2.0 * qw * qz;
38
-
39
- return Matrix[
40
- [ 1.0 - y2 - z2, xy + wz, zx - wy],
41
- [ xy - wz, 1.0 - z2 - x2, yz + wx],
42
- [ zx + wy, yz - wx, 1.0 - x2 - y2]]
43
- end
44
-
45
- alias_method :multi_inner, :* # hold original multiply processing
46
- def multi_new(rhs)
47
- if(rhs.kind_of?(Vector3))
48
- ans = self.multi_inner(rhs.to_column_vector)
49
- return Vector3.new(ans[0,0], ans[1,0], ans[2,0])
50
- end
51
- multi_inner(rhs)
52
- end
53
- alias_method :*, :multi_new # overwrite new multiply processing
54
- end
55
-