gmath3D 0.2.4 → 0.2.5
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/.document +5 -5
- data/Gemfile +5 -11
- data/LICENSE.txt +20 -20
- data/README.rdoc +19 -19
- data/Rakefile +45 -45
- data/VERSION +1 -1
- data/gmath3D.gemspec +79 -80
- data/lib/box.rb +145 -145
- data/lib/ellipse.rb +11 -11
- data/lib/ext.rb +82 -82
- data/lib/finite_line.rb +244 -244
- data/lib/geom.rb +20 -20
- data/lib/gmath3D.rb +22 -22
- data/lib/line.rb +122 -122
- data/lib/plane.rb +131 -131
- data/lib/polyline.rb +73 -73
- data/lib/quat.rb +170 -170
- data/lib/rectangle.rb +155 -155
- data/lib/tri_mesh.rb +258 -258
- data/lib/triangle.rb +281 -281
- data/lib/util.rb +36 -23
- data/lib/vector3.rb +227 -227
- data/test/helper.rb +15 -15
- data/test/test_box.rb +167 -167
- data/test/test_ellipse.rb +55 -55
- data/test/test_finite_line.rb +306 -306
- data/test/test_geom.rb +17 -17
- data/test/test_line.rb +146 -146
- data/test/test_matrix_util.rb +84 -84
- data/test/test_plane.rb +200 -200
- data/test/test_polyline.rb +93 -93
- data/test/test_quat.rb +144 -144
- data/test/test_rectangle.rb +184 -184
- data/test/test_tri_mesh.rb +186 -186
- data/test/test_triangle.rb +318 -318
- data/test/test_util.rb +88 -57
- data/test/test_vector3.rb +439 -439
- metadata +8 -11
- data/Gemfile.lock +0 -16
data/lib/quat.rb
CHANGED
@@ -1,170 +1,170 @@
|
|
1
|
-
require 'gmath3D'
|
2
|
-
|
3
|
-
module GMath3D
|
4
|
-
#
|
5
|
-
# Quat represents quaternion.
|
6
|
-
#
|
7
|
-
class Quat
|
8
|
-
public
|
9
|
-
attr_accessor :x
|
10
|
-
attr_accessor :y
|
11
|
-
attr_accessor :z
|
12
|
-
attr_accessor :w
|
13
|
-
|
14
|
-
# [Input]
|
15
|
-
# _x_, _y_, _z_, _w_should be Numeric.
|
16
|
-
# [Output]
|
17
|
-
# return new instance of Quat.
|
18
|
-
def initialize(x=0.0,y=0.0,z=0.0,w=0.0)
|
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
|
-
super()
|
24
|
-
@x = x
|
25
|
-
@y = y
|
26
|
-
@z = z
|
27
|
-
@w = w
|
28
|
-
end
|
29
|
-
|
30
|
-
# [Input]
|
31
|
-
# _axsi_ should be Vector3 and _angle_ should be Numeric.
|
32
|
-
# [Output]
|
33
|
-
# return new instance of Quat.
|
34
|
-
def self.from_axis(axis, angle)
|
35
|
-
Util3D.check_arg_type(Vector3, axis)
|
36
|
-
Util3D.check_arg_type(Numeric, angle)
|
37
|
-
s = Math.sin(0.5*angle)
|
38
|
-
x = s * axis.x
|
39
|
-
y = s * axis.y
|
40
|
-
z = s * axis.z
|
41
|
-
w = Math.cos(0.5*angle)
|
42
|
-
return Quat.new(x,y,z,w)
|
43
|
-
end
|
44
|
-
|
45
|
-
# [Input]
|
46
|
-
# _matrix_ should be Matrix which row and column size are 3.
|
47
|
-
# [Output]
|
48
|
-
# return new instance of Quat.
|
49
|
-
def self.from_matrix(mat)
|
50
|
-
fourWSquaredMinus1 = mat[0,0] + mat[1,1] + mat[2,2]
|
51
|
-
fourXSquaredMinus1 = mat[0,0] - mat[1,1] - mat[2,2]
|
52
|
-
fourYSquaredMinus1 = mat[1,1] - mat[0,0] - mat[2,2]
|
53
|
-
fourZSquaredMinus1 = mat[2,2] - mat[0,0] - mat[1,1]
|
54
|
-
|
55
|
-
biggestIndex = 0
|
56
|
-
fourBiggestSquaredMinus1 = fourWSquaredMinus1
|
57
|
-
if(fourXSquaredMinus1 > fourBiggestSquaredMinus1)
|
58
|
-
fourBiggestSquaredMinus1 = fourXSquaredMinus1
|
59
|
-
biggestIndex = 1
|
60
|
-
end
|
61
|
-
if(fourYSquaredMinus1 > fourBiggestSquaredMinus1)
|
62
|
-
fourBiggestSquaredMinus1 = fourYSquaredMinus1
|
63
|
-
biggestIndex = 2
|
64
|
-
end
|
65
|
-
if(fourZSquaredMinus1 > fourBiggestSquaredMinus1)
|
66
|
-
fourBiggestSquaredMinus1 = fourZSquaredMinus1
|
67
|
-
biggestIndex = 3
|
68
|
-
end
|
69
|
-
|
70
|
-
biggestVal = Math.sqrt(fourBiggestSquaredMinus1 + 1.0) * 0.5
|
71
|
-
multi = 0.25 / biggestVal
|
72
|
-
|
73
|
-
case biggestIndex
|
74
|
-
when 0
|
75
|
-
w = biggestVal
|
76
|
-
x = (mat[1,2] - mat[2,1]) *multi
|
77
|
-
y = (mat[2,0] - mat[0,2]) *multi
|
78
|
-
z = (mat[0,1] - mat[1,0]) *multi
|
79
|
-
when 1
|
80
|
-
x = biggestVal;
|
81
|
-
w = (mat[1,2] - mat[2,1]) *multi
|
82
|
-
y = (mat[0,1] + mat[1,0]) *multi
|
83
|
-
z = (mat[2,0] + mat[0,2]) *multi
|
84
|
-
when 2
|
85
|
-
y = biggestVal;
|
86
|
-
w = (mat[2,0] - mat[0,2]) *multi
|
87
|
-
x = (mat[0,1] + mat[1,0]) *multi
|
88
|
-
z = (mat[1,2] + mat[2,1]) *multi
|
89
|
-
when 3
|
90
|
-
z = biggestVal;
|
91
|
-
w = (mat[0,1] - mat[1,0]) *multi
|
92
|
-
x = (mat[2,0] + mat[0,2]) *multi
|
93
|
-
y = (mat[1,2] + mat[2,1]) *multi
|
94
|
-
end
|
95
|
-
return Quat.new(x,y,z,w)
|
96
|
-
end
|
97
|
-
|
98
|
-
def to_element_s
|
99
|
-
"[#{@x}, #{@y}, #{@z}, #{@w}]"
|
100
|
-
end
|
101
|
-
|
102
|
-
def to_s
|
103
|
-
"Quat" + to_element_s
|
104
|
-
end
|
105
|
-
|
106
|
-
# [Input]
|
107
|
-
# _rhs_ should be Quat.
|
108
|
-
# [Output]
|
109
|
-
# return true if rhs equals myself.
|
110
|
-
def ==(rhs)
|
111
|
-
return false if( !rhs.kind_of?(Quat) )
|
112
|
-
return false if(self.x != rhs.x)
|
113
|
-
return false if(self.y != rhs.y)
|
114
|
-
return false if(self.z != rhs.z)
|
115
|
-
return false if(self.w != rhs.w)
|
116
|
-
true
|
117
|
-
end
|
118
|
-
|
119
|
-
# [Output]
|
120
|
-
# return conjugated Quat.
|
121
|
-
def conjugate
|
122
|
-
return Quat.new( -self.x, -self.y, -self.z, self.w)
|
123
|
-
end
|
124
|
-
|
125
|
-
# [Output]
|
126
|
-
# return normalized result as Quat.
|
127
|
-
def normalize()
|
128
|
-
mag = Math.sqrt(self.x*self.x + self.y*self.y + self.z*self.z)
|
129
|
-
return Quat.new(self.x/mag, self.y/mag, self.z/mag, self.w/mag)
|
130
|
-
end
|
131
|
-
|
132
|
-
# [Input]
|
133
|
-
# _rhs_ should be Quat.
|
134
|
-
# [Output]
|
135
|
-
# return added result as Quat.
|
136
|
-
def +(rhs)
|
137
|
-
Util3D.check_arg_type(Quat, rhs)
|
138
|
-
t1 = Vector3.new(self.x, self.y, self.z)
|
139
|
-
t2 = Vector3.new(rhs.x, rhs.y, rhs.z)
|
140
|
-
dot = t1.dot(t2)
|
141
|
-
t3 = t2.cross(t1)
|
142
|
-
|
143
|
-
t1 *= rhs.w
|
144
|
-
t2 *= self.w
|
145
|
-
|
146
|
-
tf = t1 + t2 + t3
|
147
|
-
rtn_w = self.w * rhs.w - dot
|
148
|
-
|
149
|
-
return Quat.new(tf.x, tf.y, tf.z, rtn_w)
|
150
|
-
end
|
151
|
-
|
152
|
-
# [Input]
|
153
|
-
# _rsh_ should be Quat.
|
154
|
-
# [Output]
|
155
|
-
# return (outer products) multiplyed result as Quat.
|
156
|
-
def *(rhs)
|
157
|
-
Util3D.check_arg_type(Quat, rhs)
|
158
|
-
|
159
|
-
pw = self.w; px = self.x; py = self.y; pz = self.z;
|
160
|
-
qw = rhs.w ; qx = rhs.x ; qy = rhs.y ; qz = rhs.z;
|
161
|
-
|
162
|
-
w = pw * qw - px * qx - py * qy - pz * qz
|
163
|
-
x = pw * qx + px * qw + py * qz - pz * qy
|
164
|
-
y = pw * qy - px * qz + py * qw + pz * qx
|
165
|
-
z = pw * qz + px * qy - py * qx + pz * qw
|
166
|
-
return Quat.new( x,y,z,w )
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
1
|
+
require 'gmath3D'
|
2
|
+
|
3
|
+
module GMath3D
|
4
|
+
#
|
5
|
+
# Quat represents quaternion.
|
6
|
+
#
|
7
|
+
class Quat
|
8
|
+
public
|
9
|
+
attr_accessor :x
|
10
|
+
attr_accessor :y
|
11
|
+
attr_accessor :z
|
12
|
+
attr_accessor :w
|
13
|
+
|
14
|
+
# [Input]
|
15
|
+
# _x_, _y_, _z_, _w_should be Numeric.
|
16
|
+
# [Output]
|
17
|
+
# return new instance of Quat.
|
18
|
+
def initialize(x=0.0,y=0.0,z=0.0,w=0.0)
|
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
|
+
super()
|
24
|
+
@x = x
|
25
|
+
@y = y
|
26
|
+
@z = z
|
27
|
+
@w = w
|
28
|
+
end
|
29
|
+
|
30
|
+
# [Input]
|
31
|
+
# _axsi_ should be Vector3 and _angle_ should be Numeric.
|
32
|
+
# [Output]
|
33
|
+
# return new instance of Quat.
|
34
|
+
def self.from_axis(axis, angle)
|
35
|
+
Util3D.check_arg_type(Vector3, axis)
|
36
|
+
Util3D.check_arg_type(Numeric, angle)
|
37
|
+
s = Math.sin(0.5*angle)
|
38
|
+
x = s * axis.x
|
39
|
+
y = s * axis.y
|
40
|
+
z = s * axis.z
|
41
|
+
w = Math.cos(0.5*angle)
|
42
|
+
return Quat.new(x,y,z,w)
|
43
|
+
end
|
44
|
+
|
45
|
+
# [Input]
|
46
|
+
# _matrix_ should be Matrix which row and column size are 3.
|
47
|
+
# [Output]
|
48
|
+
# return new instance of Quat.
|
49
|
+
def self.from_matrix(mat)
|
50
|
+
fourWSquaredMinus1 = mat[0,0] + mat[1,1] + mat[2,2]
|
51
|
+
fourXSquaredMinus1 = mat[0,0] - mat[1,1] - mat[2,2]
|
52
|
+
fourYSquaredMinus1 = mat[1,1] - mat[0,0] - mat[2,2]
|
53
|
+
fourZSquaredMinus1 = mat[2,2] - mat[0,0] - mat[1,1]
|
54
|
+
|
55
|
+
biggestIndex = 0
|
56
|
+
fourBiggestSquaredMinus1 = fourWSquaredMinus1
|
57
|
+
if(fourXSquaredMinus1 > fourBiggestSquaredMinus1)
|
58
|
+
fourBiggestSquaredMinus1 = fourXSquaredMinus1
|
59
|
+
biggestIndex = 1
|
60
|
+
end
|
61
|
+
if(fourYSquaredMinus1 > fourBiggestSquaredMinus1)
|
62
|
+
fourBiggestSquaredMinus1 = fourYSquaredMinus1
|
63
|
+
biggestIndex = 2
|
64
|
+
end
|
65
|
+
if(fourZSquaredMinus1 > fourBiggestSquaredMinus1)
|
66
|
+
fourBiggestSquaredMinus1 = fourZSquaredMinus1
|
67
|
+
biggestIndex = 3
|
68
|
+
end
|
69
|
+
|
70
|
+
biggestVal = Math.sqrt(fourBiggestSquaredMinus1 + 1.0) * 0.5
|
71
|
+
multi = 0.25 / biggestVal
|
72
|
+
|
73
|
+
case biggestIndex
|
74
|
+
when 0
|
75
|
+
w = biggestVal
|
76
|
+
x = (mat[1,2] - mat[2,1]) *multi
|
77
|
+
y = (mat[2,0] - mat[0,2]) *multi
|
78
|
+
z = (mat[0,1] - mat[1,0]) *multi
|
79
|
+
when 1
|
80
|
+
x = biggestVal;
|
81
|
+
w = (mat[1,2] - mat[2,1]) *multi
|
82
|
+
y = (mat[0,1] + mat[1,0]) *multi
|
83
|
+
z = (mat[2,0] + mat[0,2]) *multi
|
84
|
+
when 2
|
85
|
+
y = biggestVal;
|
86
|
+
w = (mat[2,0] - mat[0,2]) *multi
|
87
|
+
x = (mat[0,1] + mat[1,0]) *multi
|
88
|
+
z = (mat[1,2] + mat[2,1]) *multi
|
89
|
+
when 3
|
90
|
+
z = biggestVal;
|
91
|
+
w = (mat[0,1] - mat[1,0]) *multi
|
92
|
+
x = (mat[2,0] + mat[0,2]) *multi
|
93
|
+
y = (mat[1,2] + mat[2,1]) *multi
|
94
|
+
end
|
95
|
+
return Quat.new(x,y,z,w)
|
96
|
+
end
|
97
|
+
|
98
|
+
def to_element_s
|
99
|
+
"[#{@x}, #{@y}, #{@z}, #{@w}]"
|
100
|
+
end
|
101
|
+
|
102
|
+
def to_s
|
103
|
+
"Quat" + to_element_s
|
104
|
+
end
|
105
|
+
|
106
|
+
# [Input]
|
107
|
+
# _rhs_ should be Quat.
|
108
|
+
# [Output]
|
109
|
+
# return true if rhs equals myself.
|
110
|
+
def ==(rhs)
|
111
|
+
return false if( !rhs.kind_of?(Quat) )
|
112
|
+
return false if(self.x != rhs.x)
|
113
|
+
return false if(self.y != rhs.y)
|
114
|
+
return false if(self.z != rhs.z)
|
115
|
+
return false if(self.w != rhs.w)
|
116
|
+
true
|
117
|
+
end
|
118
|
+
|
119
|
+
# [Output]
|
120
|
+
# return conjugated Quat.
|
121
|
+
def conjugate
|
122
|
+
return Quat.new( -self.x, -self.y, -self.z, self.w)
|
123
|
+
end
|
124
|
+
|
125
|
+
# [Output]
|
126
|
+
# return normalized result as Quat.
|
127
|
+
def normalize()
|
128
|
+
mag = Math.sqrt(self.x*self.x + self.y*self.y + self.z*self.z)
|
129
|
+
return Quat.new(self.x/mag, self.y/mag, self.z/mag, self.w/mag)
|
130
|
+
end
|
131
|
+
|
132
|
+
# [Input]
|
133
|
+
# _rhs_ should be Quat.
|
134
|
+
# [Output]
|
135
|
+
# return added result as Quat.
|
136
|
+
def +(rhs)
|
137
|
+
Util3D.check_arg_type(Quat, rhs)
|
138
|
+
t1 = Vector3.new(self.x, self.y, self.z)
|
139
|
+
t2 = Vector3.new(rhs.x, rhs.y, rhs.z)
|
140
|
+
dot = t1.dot(t2)
|
141
|
+
t3 = t2.cross(t1)
|
142
|
+
|
143
|
+
t1 *= rhs.w
|
144
|
+
t2 *= self.w
|
145
|
+
|
146
|
+
tf = t1 + t2 + t3
|
147
|
+
rtn_w = self.w * rhs.w - dot
|
148
|
+
|
149
|
+
return Quat.new(tf.x, tf.y, tf.z, rtn_w)
|
150
|
+
end
|
151
|
+
|
152
|
+
# [Input]
|
153
|
+
# _rsh_ should be Quat.
|
154
|
+
# [Output]
|
155
|
+
# return (outer products) multiplyed result as Quat.
|
156
|
+
def *(rhs)
|
157
|
+
Util3D.check_arg_type(Quat, rhs)
|
158
|
+
|
159
|
+
pw = self.w; px = self.x; py = self.y; pz = self.z;
|
160
|
+
qw = rhs.w ; qx = rhs.x ; qy = rhs.y ; qz = rhs.z;
|
161
|
+
|
162
|
+
w = pw * qw - px * qx - py * qy - pz * qz
|
163
|
+
x = pw * qx + px * qw + py * qz - pz * qy
|
164
|
+
y = pw * qy - px * qz + py * qw + pz * qx
|
165
|
+
z = pw * qz + px * qy - py * qx + pz * qw
|
166
|
+
return Quat.new( x,y,z,w )
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
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
|
+
|