gmath3D 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
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
-