gmath3D 0.1.1
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 -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
|