gmath3D 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +16 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +45 -0
- data/VERSION +1 -0
- data/gmath3D.gemspec +71 -0
- data/lib/box.rb +74 -0
- data/lib/finite_line.rb +157 -0
- data/lib/geom.rb +20 -0
- data/lib/gmath3D.rb +11 -0
- data/lib/line.rb +80 -0
- data/lib/plane.rb +86 -0
- data/lib/rectangle.rb +89 -0
- data/lib/triangle.rb +133 -0
- data/lib/util.rb +41 -0
- data/lib/vector3.rb +116 -0
- data/test/helper.rb +15 -0
- data/test/test_box.rb +90 -0
- data/test/test_finite_line.rb +245 -0
- data/test/test_geom.rb +14 -0
- data/test/test_gmath3D.rb +15 -0
- data/test/test_line.rb +105 -0
- data/test/test_plane.rb +160 -0
- data/test/test_rectangle.rb +123 -0
- data/test/test_triangle.rb +143 -0
- data/test/test_util.rb +54 -0
- data/test/test_vector3.rb +319 -0
- metadata +104 -0
data/lib/rectangle.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'matrix'
|
2
|
+
|
3
|
+
require 'gmath3D'
|
4
|
+
|
5
|
+
module GMath3D
|
6
|
+
class Rectangle < Geom
|
7
|
+
public
|
8
|
+
attr_accessor:base_point
|
9
|
+
attr_accessor:u_vector
|
10
|
+
attr_accessor:v_vector
|
11
|
+
|
12
|
+
def initialize(base_point_arg = Vector3.new(), u_vector_arg = Vector3.new(1,0,0), v_vector_arg = Vector3.new(0,1,0))
|
13
|
+
Util.check_arg_type(::Vector3, base_point_arg)
|
14
|
+
Util.check_arg_type(::Vector3, u_vector_arg)
|
15
|
+
Util.check_arg_type(::Vector3, v_vector_arg)
|
16
|
+
super()
|
17
|
+
self.base_point = base_point_arg
|
18
|
+
self.u_vector = u_vector_arg
|
19
|
+
self.v_vector = v_vector_arg
|
20
|
+
end
|
21
|
+
|
22
|
+
def point(u, v)
|
23
|
+
Util.check_arg_type(::Numeric, u)
|
24
|
+
Util.check_arg_type(::Numeric, v)
|
25
|
+
return base_point + u_vector*u + v_vector*v
|
26
|
+
end
|
27
|
+
|
28
|
+
def edges
|
29
|
+
edge_ary = Array.new(4)
|
30
|
+
edge_ary[0] = FiniteLine.new( base_point, base_point+u_vector)
|
31
|
+
edge_ary[1] = FiniteLine.new( base_point+u_vector, base_point+u_vector+v_vector)
|
32
|
+
edge_ary[2] = FiniteLine.new( base_point+u_vector+v_vector, base_point+v_vector)
|
33
|
+
edge_ary[3] = FiniteLine.new( base_point+v_vector, base_point)
|
34
|
+
return edge_ary
|
35
|
+
end
|
36
|
+
|
37
|
+
def normal
|
38
|
+
return (u_vector.cross(v_vector)).normalize()
|
39
|
+
end
|
40
|
+
|
41
|
+
def opposite_point
|
42
|
+
return base_point + u_vector + v_vector
|
43
|
+
end
|
44
|
+
|
45
|
+
def center_point
|
46
|
+
return base_point + u_vector*0.5 + v_vector*0.5
|
47
|
+
end
|
48
|
+
|
49
|
+
def area
|
50
|
+
return (u_vector.cross(v_vector)).length
|
51
|
+
end
|
52
|
+
|
53
|
+
def uv_parameter(check_point)
|
54
|
+
Util.check_arg_type(::Vector3, check_point)
|
55
|
+
mat = Matrix[[u_vector.x, u_vector.y, u_vector.z],
|
56
|
+
[v_vector.x, v_vector.y, v_vector.z],
|
57
|
+
[normal.x, normal.y, normal.z]]
|
58
|
+
vec = (check_point - base_point).to_column_vector
|
59
|
+
ans = mat.t.inv*vec
|
60
|
+
return ans[0,0], ans[1,0]
|
61
|
+
end
|
62
|
+
|
63
|
+
def distance(target)
|
64
|
+
# with Point
|
65
|
+
if(target.kind_of?(Vector3))
|
66
|
+
return distance_to_point(target)
|
67
|
+
elsif(target.kind_of?(Line))
|
68
|
+
#with Line
|
69
|
+
# return distance_to_line(target)
|
70
|
+
end
|
71
|
+
Util.raise_argurment_error(target)
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
def distance_to_point(check_point)
|
76
|
+
u,v = self.uv_parameter(check_point)
|
77
|
+
if(u >= 0 && u <= 1 && v >= 0 && v <= 1)
|
78
|
+
point_on_rect = self.point( u, v )
|
79
|
+
distance = point_on_rect.distance(check_point)
|
80
|
+
return distance, point_on_rect
|
81
|
+
end
|
82
|
+
# rectangle does not contain projected point
|
83
|
+
# check distance to FiniteLines
|
84
|
+
finite_lines = self.edges
|
85
|
+
return FiniteLine.ary_distanc_to_point(finite_lines, check_point)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
data/lib/triangle.rb
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'gmath3D'
|
2
|
+
|
3
|
+
module GMath3D
|
4
|
+
class Triangle < Geom
|
5
|
+
public
|
6
|
+
attr_accessor:vertices
|
7
|
+
|
8
|
+
def initialize(vertex_arg1 = Vector3.new(), vertex_arg2 = Vector3.new(1,0,0), vertex_arg3 = Vector3.new(0,1,0))
|
9
|
+
Util.check_arg_type(::Vector3, vertex_arg1)
|
10
|
+
Util.check_arg_type(::Vector3, vertex_arg2)
|
11
|
+
Util.check_arg_type(::Vector3, vertex_arg3)
|
12
|
+
super()
|
13
|
+
@vertices = Array.new([vertex_arg1, vertex_arg2, vertex_arg3])
|
14
|
+
end
|
15
|
+
|
16
|
+
def point( parameter )
|
17
|
+
Util.check_arg_type(::Array, parameter )
|
18
|
+
# TODO Argument check
|
19
|
+
return self.vertices[0]*parameter[0] + self.vertices[1]*parameter[1] + self.vertices[2]*parameter[2]
|
20
|
+
end
|
21
|
+
|
22
|
+
def edges
|
23
|
+
return_edges = Array.new(3)
|
24
|
+
return_edges[0] = FiniteLine.new(self.vertices[0], self.vertices[1])
|
25
|
+
return_edges[1] = FiniteLine.new(self.vertices[1], self.vertices[2])
|
26
|
+
return_edges[2] = FiniteLine.new(self.vertices[2], self.vertices[0])
|
27
|
+
return return_edges
|
28
|
+
end
|
29
|
+
|
30
|
+
def area
|
31
|
+
vec1 = vertices[1] - vertices[0]
|
32
|
+
vec2 = vertices[2] - vertices[0]
|
33
|
+
outer_product = vec1.cross(vec2)
|
34
|
+
return outer_product.length / 2.0
|
35
|
+
end
|
36
|
+
|
37
|
+
def center
|
38
|
+
return vertices.avg
|
39
|
+
end
|
40
|
+
|
41
|
+
def normal
|
42
|
+
vec1 = self.vertices[1] - self.vertices[0]
|
43
|
+
vec2 = self.vertices[2] - self.vertices[0]
|
44
|
+
return (vec1.cross(vec2).normalize)
|
45
|
+
end
|
46
|
+
|
47
|
+
def barycentric_coordinate( check_point )
|
48
|
+
Util.check_arg_type(::Vector3, check_point)
|
49
|
+
|
50
|
+
v0 = @vertices[0]
|
51
|
+
v1 = @vertices[1]
|
52
|
+
v2 = @vertices[2]
|
53
|
+
|
54
|
+
d1 = v1 - v0
|
55
|
+
d2 = v2 - v1
|
56
|
+
n = d1.cross(d2);
|
57
|
+
if((n.x).abs >= (n.y).abs && (n.x).abs >= (n.z).abs)
|
58
|
+
uu1 = v0.y - v2.y;
|
59
|
+
uu2 = v1.y - v2.y;
|
60
|
+
uu3 = check_point.y - v0.y;
|
61
|
+
uu4 = check_point.y - v2.y;
|
62
|
+
vv1 = v0.z - v2.z;
|
63
|
+
vv2 = v1.z - v2.z;
|
64
|
+
vv3 = check_point.z - v0.z;
|
65
|
+
vv4 = check_point.z - v2.z;
|
66
|
+
elsif((n.y).abs >= (n.z).abs)
|
67
|
+
uu1 = v0.z - v2.z;
|
68
|
+
uu2 = v1.z - v2.z;
|
69
|
+
uu3 = check_point.z - v0.z;
|
70
|
+
uu4 = check_point.z - v2.z;
|
71
|
+
vv1 = v0.x - v2.x;
|
72
|
+
vv2 = v1.x - v2.x;
|
73
|
+
vv3 = check_point.x - v0.x;
|
74
|
+
vv4 = check_point.x - v2.x;
|
75
|
+
else
|
76
|
+
uu1 = v0.x - v2.x;
|
77
|
+
uu2 = v1.x - v2.x;
|
78
|
+
uu3 = check_point.x - v0.x;
|
79
|
+
uu4 = check_point.x - v2.x;
|
80
|
+
vv1 = v0.y - v2.y;
|
81
|
+
vv2 = v1.y - v2.y;
|
82
|
+
vv3 = check_point.y - v0.y;
|
83
|
+
vv4 = check_point.y - v2.y;
|
84
|
+
end
|
85
|
+
|
86
|
+
denom = vv1 * uu2 - vv2* uu1
|
87
|
+
if(denom == 0.0)
|
88
|
+
return nil
|
89
|
+
end
|
90
|
+
b = Array.new(3)
|
91
|
+
oneOverDenom = 1.0 / denom ;
|
92
|
+
b[0] = (vv4*uu2 - vv2*uu4) * oneOverDenom;
|
93
|
+
b[1] = (vv1*uu3 - vv3*uu1) * oneOverDenom;
|
94
|
+
b[2] = 1.0 - b[0] - b[1];
|
95
|
+
return b;
|
96
|
+
end
|
97
|
+
|
98
|
+
def distance(target)
|
99
|
+
# with Point
|
100
|
+
if(target.kind_of?(Vector3))
|
101
|
+
return distance_to_point(target)
|
102
|
+
elsif(target.kind_of?(Line))
|
103
|
+
#with Line
|
104
|
+
# return distance_to_line(target)
|
105
|
+
end
|
106
|
+
Util.raise_argurment_error(target)
|
107
|
+
end
|
108
|
+
|
109
|
+
def contains( check_point )
|
110
|
+
Util.check_arg_type(Vector3, check_point )
|
111
|
+
plane = Plane.new( vertices[0], self.normal)
|
112
|
+
distance, projected_point = plane.distance(check_point)
|
113
|
+
return false if( distance > self.tolerance )
|
114
|
+
g_coord = self.barycentric_coordinate(check_point)
|
115
|
+
g_coord.each do |item|
|
116
|
+
return false if( item < 0 or 1 < item)
|
117
|
+
end
|
118
|
+
return true
|
119
|
+
end
|
120
|
+
private
|
121
|
+
def distance_to_point(target_point)
|
122
|
+
plane = Plane.new( vertices[0], self.normal)
|
123
|
+
distance, projected_point = plane.distance(target_point)
|
124
|
+
if( self.contains(projected_point))
|
125
|
+
return distance, projected_point
|
126
|
+
end
|
127
|
+
#check distance to FiniteLines
|
128
|
+
finite_lines = self.edges
|
129
|
+
return FiniteLine.ary_distanc_to_point(finite_lines, target_point)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
data/lib/util.rb
ADDED
@@ -0,0 +1,41 @@
|
|
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
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.raise_argurment_error(instance)
|
10
|
+
raise(ArgumentError::new("type mismatch: #{instance.class}"))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Array
|
16
|
+
public
|
17
|
+
def sum
|
18
|
+
s, n = self.sum_with_number
|
19
|
+
return s
|
20
|
+
end
|
21
|
+
def avg
|
22
|
+
s, n = self.sum_with_number
|
23
|
+
return s / n
|
24
|
+
end
|
25
|
+
|
26
|
+
def sum_with_number
|
27
|
+
return nil, 0 if(self.size <= 0)
|
28
|
+
s = nil
|
29
|
+
n = 0
|
30
|
+
self.each do |v|
|
31
|
+
next if v.nil?
|
32
|
+
if(s==nil)
|
33
|
+
s = v
|
34
|
+
else
|
35
|
+
s += v
|
36
|
+
end
|
37
|
+
n += 1
|
38
|
+
end
|
39
|
+
return s, n
|
40
|
+
end
|
41
|
+
end
|
data/lib/vector3.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'gmath3D'
|
2
|
+
|
3
|
+
module GMath3D
|
4
|
+
class Vector3 < Geom
|
5
|
+
public
|
6
|
+
attr_accessor :x
|
7
|
+
attr_accessor :y
|
8
|
+
attr_accessor :z
|
9
|
+
|
10
|
+
def initialize(x=0.0,y=0.0,z=0.0)
|
11
|
+
super()
|
12
|
+
@x = x
|
13
|
+
@y = y
|
14
|
+
@z = z
|
15
|
+
end
|
16
|
+
def ==(rhs)
|
17
|
+
equals_inner(rhs)
|
18
|
+
end
|
19
|
+
def +(rhs)
|
20
|
+
add(rhs)
|
21
|
+
end
|
22
|
+
def -(rhs)
|
23
|
+
subtract(rhs)
|
24
|
+
end
|
25
|
+
def *(rhs)
|
26
|
+
multiply(rhs)
|
27
|
+
end
|
28
|
+
def /(rhs)
|
29
|
+
divide(rhs)
|
30
|
+
end
|
31
|
+
|
32
|
+
def dot(rhs)
|
33
|
+
Util.check_arg_type(Vector3, rhs)
|
34
|
+
self.x*rhs.x + self.y*rhs.y + self.z*rhs.z
|
35
|
+
end
|
36
|
+
def cross(rhs)
|
37
|
+
Util.check_arg_type(Vector3, rhs)
|
38
|
+
Vector3.new(
|
39
|
+
self.y*rhs.z - self.z*rhs.y,
|
40
|
+
self.z*rhs.x - self.x*rhs.z,
|
41
|
+
self.x*rhs.y - self.y*rhs.x)
|
42
|
+
end
|
43
|
+
|
44
|
+
def length
|
45
|
+
Math::sqrt(self.x*self.x + self.y*self.y + self.z*self.z)
|
46
|
+
end
|
47
|
+
def distance(rhs)
|
48
|
+
Util.check_arg_type(Vector3, rhs)
|
49
|
+
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))
|
50
|
+
end
|
51
|
+
def distance(rhs)
|
52
|
+
Util.check_arg_type(Vector3, rhs)
|
53
|
+
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))
|
54
|
+
end
|
55
|
+
|
56
|
+
def angle(rhs)
|
57
|
+
Util.check_arg_type(Vector3, rhs)
|
58
|
+
vec1Length = self.length ;
|
59
|
+
vec2Length = rhs.length ;
|
60
|
+
return 0.0 if(vec1Length*vec2Length < self.tolerance )
|
61
|
+
v = self.dot(rhs)/(vec1Length*vec2Length)
|
62
|
+
Math::acos( v )
|
63
|
+
end
|
64
|
+
def normalize()
|
65
|
+
self / self.length.to_f
|
66
|
+
end
|
67
|
+
|
68
|
+
def parallel?(rhs)
|
69
|
+
Util.check_arg_type(Vector3, rhs)
|
70
|
+
return false if(self.length < self.tolerance or rhs.length < rhs.tolerance)
|
71
|
+
return false if(self.cross(rhs).length > self.tolerance)
|
72
|
+
return true
|
73
|
+
end
|
74
|
+
def same_direction?(rhs)
|
75
|
+
Util.check_arg_type(Vector3, rhs)
|
76
|
+
return false if(!parallel?(rhs))
|
77
|
+
return false if(self.dot(rhs) < self.tolerance)
|
78
|
+
return true
|
79
|
+
end
|
80
|
+
|
81
|
+
def project_to(rhs)
|
82
|
+
Util.check_arg_type(Vector3, rhs)
|
83
|
+
return Vector3.new, 0.0 if( rhs.length < rhs.tolerance )
|
84
|
+
parameter = self.dot( rhs ) / ( rhs.x * rhs.x + rhs.y * rhs.y + rhs.z * rhs.z ).to_f
|
85
|
+
return rhs*parameter, parameter
|
86
|
+
end
|
87
|
+
def to_column_vector
|
88
|
+
return Matrix.column_vector([x,y,z])
|
89
|
+
end
|
90
|
+
private
|
91
|
+
def equals_inner(rhs)
|
92
|
+
return false if( !rhs.kind_of?(Vector3) )
|
93
|
+
return false if((self.x - rhs.x).abs > @tolerance)
|
94
|
+
return false if((self.y - rhs.y).abs > @tolerance)
|
95
|
+
return false if((self.z - rhs.z).abs > @tolerance)
|
96
|
+
true
|
97
|
+
end
|
98
|
+
def add(rhs)
|
99
|
+
Util.check_arg_type(Vector3, rhs)
|
100
|
+
Vector3.new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z)
|
101
|
+
end
|
102
|
+
def subtract(rhs)
|
103
|
+
Util.check_arg_type(Vector3, rhs)
|
104
|
+
Vector3.new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z)
|
105
|
+
end
|
106
|
+
def multiply(rhs)
|
107
|
+
Util.check_arg_type(::Numeric, rhs)
|
108
|
+
Vector3.new(self.x * rhs, self.y * rhs, self.z * rhs)
|
109
|
+
end
|
110
|
+
def divide(rhs)
|
111
|
+
Util.check_arg_type(::Numeric, rhs)
|
112
|
+
Vector3.new(self.x.to_f / rhs, self.y / rhs.to_f, self.z / rhs.to_f)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
data/test/helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
|
4
|
+
begin
|
5
|
+
Bundler.setup(:default, :development)
|
6
|
+
rescue Bundler::BundlerError => e
|
7
|
+
$stderr.puts e.message
|
8
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
9
|
+
exit e.status_code
|
10
|
+
end
|
11
|
+
require 'minitest/unit'
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
+
|
15
|
+
require 'gmath3D'
|
data/test/test_box.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'box'
|
2
|
+
|
3
|
+
include GMath3D
|
4
|
+
|
5
|
+
MiniTest::Unit.autorun
|
6
|
+
|
7
|
+
class BoxTestCase < MiniTest::Unit::TestCase
|
8
|
+
def setup
|
9
|
+
@box_default = Box.new()
|
10
|
+
@box = Box.new(Vector3.new(-3,2,5), Vector3.new(2,-2.5, 0))
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_initalize
|
14
|
+
assert_equal(0, @box_default.min_point.x)
|
15
|
+
assert_equal(0, @box_default.min_point.y)
|
16
|
+
assert_equal(0, @box_default.min_point.z)
|
17
|
+
assert_equal(1, @box_default.max_point.x)
|
18
|
+
assert_equal(1, @box_default.max_point.y)
|
19
|
+
assert_equal(1, @box_default.max_point.z)
|
20
|
+
|
21
|
+
assert_equal(-3.0, @box.min_point.x)
|
22
|
+
assert_equal(-2.5, @box.min_point.y)
|
23
|
+
assert_equal(0.0 , @box.min_point.z)
|
24
|
+
assert_equal(2.0 , @box.max_point.x)
|
25
|
+
assert_equal(2.0 , @box.max_point.y)
|
26
|
+
assert_equal(5.0 , @box.max_point.z)
|
27
|
+
|
28
|
+
assert_equal(Geom.default_tolerance, @box_default.tolerance)
|
29
|
+
|
30
|
+
assert_raises ArgumentError do
|
31
|
+
invalidResult = Box.new(nil)
|
32
|
+
end
|
33
|
+
assert_raises ArgumentError do
|
34
|
+
invalidResult = Box.new(Vector3.new(), 4.0)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_equal
|
39
|
+
shallow_copied = @box
|
40
|
+
assert( shallow_copied == @box )
|
41
|
+
assert( shallow_copied.equal?( @box ) )
|
42
|
+
|
43
|
+
deep_copied = Box.new(Vector3.new(-3,2,5), Vector3.new(2,-2.5, 0))
|
44
|
+
assert( deep_copied == @box )
|
45
|
+
assert( !deep_copied.equal?( @box ) )
|
46
|
+
|
47
|
+
assert( @box != 5 )
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_add
|
51
|
+
added_box = @box_default + Vector3.new(-2, 0.5, 3)
|
52
|
+
assert_equal(Vector3.new(-2,0,0), added_box.min_point)
|
53
|
+
assert_equal(Vector3.new(1,1,3) , added_box.max_point)
|
54
|
+
|
55
|
+
added_box = @box_default + Box.new( Vector3.new(-2,0.5, 3), Vector3.new(4, 0, 2.0))
|
56
|
+
assert_equal(Vector3.new(-2,0,0), added_box.min_point)
|
57
|
+
assert_equal(Vector3.new(4,1,3) , added_box.max_point)
|
58
|
+
|
59
|
+
point_ary = [Vector3.new(1,4,9), Vector3.new(4,-2,4), Vector3.new(2,-5,0)]
|
60
|
+
added_box = @box + point_ary
|
61
|
+
assert_equal(Vector3.new(-3,-5, 0), added_box.min_point)
|
62
|
+
assert_equal(Vector3.new( 4, 4, 9), added_box.max_point)
|
63
|
+
|
64
|
+
assert_raises ArgumentError do
|
65
|
+
invalidResult = @box + 4
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_center
|
70
|
+
assert_equal( Vector3.new(0.5, 0.5, 0.5), @box_default.center)
|
71
|
+
assert_equal( Vector3.new(-0.5,-0.25,2.5), @box.center)
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_length
|
75
|
+
width, height, depth = @box_default.length
|
76
|
+
assert_in_delta( 1, width , @box_default.tolerance)
|
77
|
+
assert_in_delta( 1, height, @box_default.tolerance)
|
78
|
+
assert_in_delta( 1, depth , @box_default.tolerance)
|
79
|
+
|
80
|
+
width, height, depth = @box.length
|
81
|
+
assert_in_delta( 5.0, width , @box.tolerance)
|
82
|
+
assert_in_delta( 4.5, height, @box.tolerance)
|
83
|
+
assert_in_delta( 5.0, depth , @box.tolerance)
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_volume
|
87
|
+
assert_in_delta( 1.0, @box_default.volume, @box_default.tolerance )
|
88
|
+
assert_in_delta( 112.5, @box.volume, @box.tolerance )
|
89
|
+
end
|
90
|
+
end
|