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/line.rb
CHANGED
@@ -1,122 +1,122 @@
|
|
1
|
-
require 'gmath3D'
|
2
|
-
|
3
|
-
module GMath3D
|
4
|
-
#
|
5
|
-
# Line represents a infinite line on 3D space.
|
6
|
-
#
|
7
|
-
class Line < Geom
|
8
|
-
public
|
9
|
-
attr_accessor :base_point
|
10
|
-
attr_accessor :direction
|
11
|
-
|
12
|
-
def to_s
|
13
|
-
"Line[point#{@base_point.to_element_s}, vector#{@direction.to_element_s}"
|
14
|
-
end
|
15
|
-
|
16
|
-
# [Input]
|
17
|
-
# _point_ and _direction_ should be Vector3.
|
18
|
-
# [Output]
|
19
|
-
# return new instance of Line.
|
20
|
-
def initialize(point = Vector3.new(0.0,0.0,0.0), direction = Vector3.new(1.0,0.0,0.0))
|
21
|
-
Util3D.check_arg_type(Vector3, point)
|
22
|
-
Util3D.check_arg_type(Vector3, direction)
|
23
|
-
super()
|
24
|
-
@base_point = point
|
25
|
-
@direction = direction
|
26
|
-
end
|
27
|
-
|
28
|
-
def initialize_copy( original_obj )
|
29
|
-
@base_point = original_obj.base_point.dup
|
30
|
-
@direction = original_obj.direction.dup
|
31
|
-
end
|
32
|
-
|
33
|
-
# [Input]
|
34
|
-
# _rhs_ is Line.
|
35
|
-
# [Output]
|
36
|
-
# return true if rhs equals myself.
|
37
|
-
def ==(rhs)
|
38
|
-
return false if rhs == nil
|
39
|
-
return false if( !rhs.kind_of?(Line) )
|
40
|
-
return false if( self.base_point != rhs.base_point)
|
41
|
-
return false if( self.direction != rhs.direction)
|
42
|
-
return true
|
43
|
-
end
|
44
|
-
|
45
|
-
# [Input]
|
46
|
-
# _parameter_ should be Numeric.
|
47
|
-
# [Output]
|
48
|
-
# return a point on line at input parameter position as Vector3
|
49
|
-
def point(parameter)
|
50
|
-
Util3D.check_arg_type(::Numeric, parameter)
|
51
|
-
@base_point + @direction*parameter
|
52
|
-
end
|
53
|
-
|
54
|
-
# This function returns closest distance between Line and anothor element.
|
55
|
-
# [Input]
|
56
|
-
# _target_ should be Vector3 or Line.
|
57
|
-
#
|
58
|
-
# [Output]
|
59
|
-
# [in case _target_ is Vector3]
|
60
|
-
# return "distance, closest point on myself, parameter on myself" as [Numeric, Vector3, Numeric]
|
61
|
-
# [in case _target_ is Line]
|
62
|
-
# return "distance, point on myself, point on target, parameter on myself, parameter on tatget"
|
63
|
-
# as [Numeric, Vector3, Vector3, Numeric, Numeric]
|
64
|
-
def distance(target)
|
65
|
-
# with Point
|
66
|
-
if(target.kind_of?(Vector3))
|
67
|
-
return distance_to_point(target)
|
68
|
-
#with Line
|
69
|
-
elsif(target.kind_of?(Line))
|
70
|
-
return distance_to_line(target)
|
71
|
-
end
|
72
|
-
Util3D.raise_argurment_error(target)
|
73
|
-
end
|
74
|
-
|
75
|
-
private
|
76
|
-
def distance_to_point(target_point)
|
77
|
-
point_on_line1 = self.base_point
|
78
|
-
point_on_line2 = self.base_point + self.direction
|
79
|
-
|
80
|
-
vecAB = point_on_line2 - point_on_line1
|
81
|
-
vecAP = target_point - point_on_line1
|
82
|
-
vecAQ, parameter = vecAP.project_to(vecAB)
|
83
|
-
cross_point = point_on_line1 + vecAQ
|
84
|
-
vecPQ = vecAQ - vecAP
|
85
|
-
return vecPQ.length, cross_point, parameter
|
86
|
-
end
|
87
|
-
|
88
|
-
def distance_to_line(target_line)
|
89
|
-
if(self.direction.parallel?(target_line.direction)) then
|
90
|
-
distanceInfo = self.distance(target_line.base_point)
|
91
|
-
return distanceInfo[0], nil, nil, nil, nil
|
92
|
-
else
|
93
|
-
line1_point1 = self.base_point
|
94
|
-
line1_point2 = self.base_point + self.direction
|
95
|
-
line2_point1 = target_line.base_point
|
96
|
-
line2_point2 = target_line.base_point + target_line.direction
|
97
|
-
|
98
|
-
vec_da = line1_point2 - line1_point1
|
99
|
-
vec_db = line2_point2 - line2_point1
|
100
|
-
vec_ab = line2_point1 - line1_point1
|
101
|
-
|
102
|
-
abs_vec_db = vec_db.length*vec_db.length
|
103
|
-
abs_vec_da = vec_da.length*vec_da.length
|
104
|
-
|
105
|
-
delta = (abs_vec_da*abs_vec_db - vec_da.dot( vec_db )*vec_da.dot( vec_db ))
|
106
|
-
|
107
|
-
if( delta < self.tolerance )
|
108
|
-
# TODO ASSERT(false)
|
109
|
-
return nil
|
110
|
-
end
|
111
|
-
parameter1 = (abs_vec_db*vec_ab.dot(vec_da) - vec_da.dot( vec_db )*vec_ab.dot( vec_db ) ) / delta
|
112
|
-
parameter2 = (vec_da.dot( vec_db )*vec_ab.dot( vec_da ) - abs_vec_da*vec_ab.dot( vec_db ))/ delta
|
113
|
-
|
114
|
-
line1_closest_point = line1_point1 + vec_da*parameter1
|
115
|
-
line2_closest_point = line2_point1 + vec_db*parameter2
|
116
|
-
distance = line1_closest_point.distance( line2_closest_point )
|
117
|
-
return distance, line1_closest_point, line2_closest_point, parameter1, parameter2
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
1
|
+
require 'gmath3D'
|
2
|
+
|
3
|
+
module GMath3D
|
4
|
+
#
|
5
|
+
# Line represents a infinite line on 3D space.
|
6
|
+
#
|
7
|
+
class Line < Geom
|
8
|
+
public
|
9
|
+
attr_accessor :base_point
|
10
|
+
attr_accessor :direction
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
"Line[point#{@base_point.to_element_s}, vector#{@direction.to_element_s}"
|
14
|
+
end
|
15
|
+
|
16
|
+
# [Input]
|
17
|
+
# _point_ and _direction_ should be Vector3.
|
18
|
+
# [Output]
|
19
|
+
# return new instance of Line.
|
20
|
+
def initialize(point = Vector3.new(0.0,0.0,0.0), direction = Vector3.new(1.0,0.0,0.0))
|
21
|
+
Util3D.check_arg_type(Vector3, point)
|
22
|
+
Util3D.check_arg_type(Vector3, direction)
|
23
|
+
super()
|
24
|
+
@base_point = point
|
25
|
+
@direction = direction
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize_copy( original_obj )
|
29
|
+
@base_point = original_obj.base_point.dup
|
30
|
+
@direction = original_obj.direction.dup
|
31
|
+
end
|
32
|
+
|
33
|
+
# [Input]
|
34
|
+
# _rhs_ is Line.
|
35
|
+
# [Output]
|
36
|
+
# return true if rhs equals myself.
|
37
|
+
def ==(rhs)
|
38
|
+
return false if rhs == nil
|
39
|
+
return false if( !rhs.kind_of?(Line) )
|
40
|
+
return false if( self.base_point != rhs.base_point)
|
41
|
+
return false if( self.direction != rhs.direction)
|
42
|
+
return true
|
43
|
+
end
|
44
|
+
|
45
|
+
# [Input]
|
46
|
+
# _parameter_ should be Numeric.
|
47
|
+
# [Output]
|
48
|
+
# return a point on line at input parameter position as Vector3
|
49
|
+
def point(parameter)
|
50
|
+
Util3D.check_arg_type(::Numeric, parameter)
|
51
|
+
@base_point + @direction*parameter
|
52
|
+
end
|
53
|
+
|
54
|
+
# This function returns closest distance between Line and anothor element.
|
55
|
+
# [Input]
|
56
|
+
# _target_ should be Vector3 or Line.
|
57
|
+
#
|
58
|
+
# [Output]
|
59
|
+
# [in case _target_ is Vector3]
|
60
|
+
# return "distance, closest point on myself, parameter on myself" as [Numeric, Vector3, Numeric]
|
61
|
+
# [in case _target_ is Line]
|
62
|
+
# return "distance, point on myself, point on target, parameter on myself, parameter on tatget"
|
63
|
+
# as [Numeric, Vector3, Vector3, Numeric, Numeric]
|
64
|
+
def distance(target)
|
65
|
+
# with Point
|
66
|
+
if(target.kind_of?(Vector3))
|
67
|
+
return distance_to_point(target)
|
68
|
+
#with Line
|
69
|
+
elsif(target.kind_of?(Line))
|
70
|
+
return distance_to_line(target)
|
71
|
+
end
|
72
|
+
Util3D.raise_argurment_error(target)
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
def distance_to_point(target_point)
|
77
|
+
point_on_line1 = self.base_point
|
78
|
+
point_on_line2 = self.base_point + self.direction
|
79
|
+
|
80
|
+
vecAB = point_on_line2 - point_on_line1
|
81
|
+
vecAP = target_point - point_on_line1
|
82
|
+
vecAQ, parameter = vecAP.project_to(vecAB)
|
83
|
+
cross_point = point_on_line1 + vecAQ
|
84
|
+
vecPQ = vecAQ - vecAP
|
85
|
+
return vecPQ.length, cross_point, parameter
|
86
|
+
end
|
87
|
+
|
88
|
+
def distance_to_line(target_line)
|
89
|
+
if(self.direction.parallel?(target_line.direction)) then
|
90
|
+
distanceInfo = self.distance(target_line.base_point)
|
91
|
+
return distanceInfo[0], nil, nil, nil, nil
|
92
|
+
else
|
93
|
+
line1_point1 = self.base_point
|
94
|
+
line1_point2 = self.base_point + self.direction
|
95
|
+
line2_point1 = target_line.base_point
|
96
|
+
line2_point2 = target_line.base_point + target_line.direction
|
97
|
+
|
98
|
+
vec_da = line1_point2 - line1_point1
|
99
|
+
vec_db = line2_point2 - line2_point1
|
100
|
+
vec_ab = line2_point1 - line1_point1
|
101
|
+
|
102
|
+
abs_vec_db = vec_db.length*vec_db.length
|
103
|
+
abs_vec_da = vec_da.length*vec_da.length
|
104
|
+
|
105
|
+
delta = (abs_vec_da*abs_vec_db - vec_da.dot( vec_db )*vec_da.dot( vec_db ))
|
106
|
+
|
107
|
+
if( delta < self.tolerance )
|
108
|
+
# TODO ASSERT(false)
|
109
|
+
return nil
|
110
|
+
end
|
111
|
+
parameter1 = (abs_vec_db*vec_ab.dot(vec_da) - vec_da.dot( vec_db )*vec_ab.dot( vec_db ) ) / delta
|
112
|
+
parameter2 = (vec_da.dot( vec_db )*vec_ab.dot( vec_da ) - abs_vec_da*vec_ab.dot( vec_db ))/ delta
|
113
|
+
|
114
|
+
line1_closest_point = line1_point1 + vec_da*parameter1
|
115
|
+
line2_closest_point = line2_point1 + vec_db*parameter2
|
116
|
+
distance = line1_closest_point.distance( line2_closest_point )
|
117
|
+
return distance, line1_closest_point, line2_closest_point, parameter1, parameter2
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
data/lib/plane.rb
CHANGED
@@ -1,131 +1,131 @@
|
|
1
|
-
require 'gmath3D'
|
2
|
-
|
3
|
-
module GMath3D
|
4
|
-
#
|
5
|
-
# Plane represents a infinite plane on 3D space.
|
6
|
-
#
|
7
|
-
class Plane < Geom
|
8
|
-
attr_accessor:base_point
|
9
|
-
attr_accessor:normal
|
10
|
-
|
11
|
-
# [Input]
|
12
|
-
# _base_point_ and _normal_ should be Vector3.
|
13
|
-
# [Output]
|
14
|
-
# returns new instance of Plane.
|
15
|
-
def initialize(base_point = Vector3.new(), normal = Vector3.new(0,0,1))
|
16
|
-
Util3D.check_arg_type(::Vector3, normal)
|
17
|
-
Util3D.check_arg_type(::Vector3, base_point)
|
18
|
-
super()
|
19
|
-
@base_point = base_point
|
20
|
-
@normal = normal.normalize()
|
21
|
-
end
|
22
|
-
|
23
|
-
def initialize_copy( original_obj )
|
24
|
-
@base_point = original_obj.base_point.dup
|
25
|
-
@normal = original_obj.normal.dup
|
26
|
-
end
|
27
|
-
|
28
|
-
# [Input]
|
29
|
-
# _rhs_ is Plane.
|
30
|
-
# [Output]
|
31
|
-
# return true if rhs equals myself.
|
32
|
-
def ==(rhs)
|
33
|
-
return false if rhs == nil
|
34
|
-
return false if( !rhs.kind_of?(Plane) )
|
35
|
-
return false if( self.base_point != rhs.base_point)
|
36
|
-
return false if( self.normal != rhs.normal)
|
37
|
-
return true
|
38
|
-
end
|
39
|
-
|
40
|
-
def to_s
|
41
|
-
"Plane[point#{@base_point.to_element_s}, normal#{@normal.to_element_s}]"
|
42
|
-
end
|
43
|
-
|
44
|
-
# This function returns closest distance between Line and anothor element.
|
45
|
-
# [Input]
|
46
|
-
# _target_ should be Vector3 or Line or FiniteLine or Plane.
|
47
|
-
#
|
48
|
-
# [Output]
|
49
|
-
# [in case _target_ is Vector3]
|
50
|
-
# return "distance, closest point on myself" as [Numeric, Vector3].
|
51
|
-
# [in case _target_ is Line]
|
52
|
-
# return "distance, intersect point, parameter on tatget" as [Numeric, Vector3, Numeric].
|
53
|
-
# [in case _target_ is FiniteLine]
|
54
|
-
# return "distance, point on plane, point on target, parameter on target"
|
55
|
-
# as [Numeric, Vector3, Vector3, Numeric].
|
56
|
-
# [in case _target_ is Plane]
|
57
|
-
# return "distance, intersect line" as [Numeric, Vector3].
|
58
|
-
def distance(target)
|
59
|
-
# with Point
|
60
|
-
if(target.kind_of?(Vector3))
|
61
|
-
return distance_to_point(target)
|
62
|
-
#with Line
|
63
|
-
elsif(target.kind_of?(Line))
|
64
|
-
return distance_to_line(target)
|
65
|
-
#with FiniteLine
|
66
|
-
elsif(target.kind_of?(FiniteLine))
|
67
|
-
return distance_to_finite_line(target)
|
68
|
-
#with Plane
|
69
|
-
elsif(target.kind_of?(Plane))
|
70
|
-
return distance_to_plane(target)
|
71
|
-
end
|
72
|
-
Util3D.raise_argurment_error(target)
|
73
|
-
end
|
74
|
-
|
75
|
-
# [Input]
|
76
|
-
# _target_point_ should be Vector3.
|
77
|
-
# [Output]
|
78
|
-
# retrun projected point on plane as Vector3.
|
79
|
-
def project( target_point )
|
80
|
-
Util3D.check_arg_type(::Vector3, target_point)
|
81
|
-
distance, closest_point = self.distance( target_point )
|
82
|
-
return closest_point
|
83
|
-
end
|
84
|
-
private
|
85
|
-
def distance_to_point(target_point)
|
86
|
-
vector_QA = target_point - @base_point
|
87
|
-
distance = vector_QA.dot(@normal)
|
88
|
-
closest_point = target_point - @normal*distance
|
89
|
-
return distance.abs, closest_point
|
90
|
-
end
|
91
|
-
|
92
|
-
def distance_to_line(target_line)
|
93
|
-
inner_product_normal_and_line_vec = target_line.direction.dot(self.normal)
|
94
|
-
#parallel
|
95
|
-
if( inner_product_normal_and_line_vec.abs < @tolerance)
|
96
|
-
distance, closest_point = self.distance(target_line.base_point)
|
97
|
-
return distance, nil,nil
|
98
|
-
end
|
99
|
-
parameter = ( self.normal.dot(self.base_point) - self.normal.dot( target_line.base_point ) )/inner_product_normal_and_line_vec.to_f
|
100
|
-
intersect_point = target_line.point(parameter)
|
101
|
-
return 0.0, intersect_point, parameter
|
102
|
-
end
|
103
|
-
|
104
|
-
def distance_to_finite_line(target_finite_line)
|
105
|
-
target_infinite_line = Line.new(target_finite_line.start_point, target_finite_line.direction)
|
106
|
-
distance, intersect_point, parameter = self.distance(target_infinite_line)
|
107
|
-
point_on_line = intersect_point
|
108
|
-
point_on_plane = intersect_point
|
109
|
-
if(parameter != nil and (parameter < 0 or 1 < parameter))
|
110
|
-
parameter = [0, parameter].max
|
111
|
-
parameter = [1, parameter].min
|
112
|
-
point_on_line = target_finite_line.point(parameter)
|
113
|
-
distance, point_on_plane = self.distance(point_on_line)
|
114
|
-
end
|
115
|
-
return distance, point_on_plane, point_on_line, parameter
|
116
|
-
end
|
117
|
-
def distance_to_plane(target_plane)
|
118
|
-
line_vector = target_plane.normal.cross(self.normal)
|
119
|
-
if(target_plane.normal.parallel?(self.normal))
|
120
|
-
distance, point_on_plane = self.distance(target_plane.base_point)
|
121
|
-
return distance, nil
|
122
|
-
end
|
123
|
-
line_vector = line_vector.normalize()
|
124
|
-
tangent_vector_on_target_plane = line_vector.cross(target_plane.normal)
|
125
|
-
distance, intersect_point, parameter = self.distance(Line.new( target_plane.base_point, tangent_vector_on_target_plane))
|
126
|
-
intersect_line = Line.new(intersect_point, line_vector)
|
127
|
-
return 0, intersect_line
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
1
|
+
require 'gmath3D'
|
2
|
+
|
3
|
+
module GMath3D
|
4
|
+
#
|
5
|
+
# Plane represents a infinite plane on 3D space.
|
6
|
+
#
|
7
|
+
class Plane < Geom
|
8
|
+
attr_accessor:base_point
|
9
|
+
attr_accessor:normal
|
10
|
+
|
11
|
+
# [Input]
|
12
|
+
# _base_point_ and _normal_ should be Vector3.
|
13
|
+
# [Output]
|
14
|
+
# returns new instance of Plane.
|
15
|
+
def initialize(base_point = Vector3.new(), normal = Vector3.new(0,0,1))
|
16
|
+
Util3D.check_arg_type(::Vector3, normal)
|
17
|
+
Util3D.check_arg_type(::Vector3, base_point)
|
18
|
+
super()
|
19
|
+
@base_point = base_point
|
20
|
+
@normal = normal.normalize()
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize_copy( original_obj )
|
24
|
+
@base_point = original_obj.base_point.dup
|
25
|
+
@normal = original_obj.normal.dup
|
26
|
+
end
|
27
|
+
|
28
|
+
# [Input]
|
29
|
+
# _rhs_ is Plane.
|
30
|
+
# [Output]
|
31
|
+
# return true if rhs equals myself.
|
32
|
+
def ==(rhs)
|
33
|
+
return false if rhs == nil
|
34
|
+
return false if( !rhs.kind_of?(Plane) )
|
35
|
+
return false if( self.base_point != rhs.base_point)
|
36
|
+
return false if( self.normal != rhs.normal)
|
37
|
+
return true
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_s
|
41
|
+
"Plane[point#{@base_point.to_element_s}, normal#{@normal.to_element_s}]"
|
42
|
+
end
|
43
|
+
|
44
|
+
# This function returns closest distance between Line and anothor element.
|
45
|
+
# [Input]
|
46
|
+
# _target_ should be Vector3 or Line or FiniteLine or Plane.
|
47
|
+
#
|
48
|
+
# [Output]
|
49
|
+
# [in case _target_ is Vector3]
|
50
|
+
# return "distance, closest point on myself" as [Numeric, Vector3].
|
51
|
+
# [in case _target_ is Line]
|
52
|
+
# return "distance, intersect point, parameter on tatget" as [Numeric, Vector3, Numeric].
|
53
|
+
# [in case _target_ is FiniteLine]
|
54
|
+
# return "distance, point on plane, point on target, parameter on target"
|
55
|
+
# as [Numeric, Vector3, Vector3, Numeric].
|
56
|
+
# [in case _target_ is Plane]
|
57
|
+
# return "distance, intersect line" as [Numeric, Vector3].
|
58
|
+
def distance(target)
|
59
|
+
# with Point
|
60
|
+
if(target.kind_of?(Vector3))
|
61
|
+
return distance_to_point(target)
|
62
|
+
#with Line
|
63
|
+
elsif(target.kind_of?(Line))
|
64
|
+
return distance_to_line(target)
|
65
|
+
#with FiniteLine
|
66
|
+
elsif(target.kind_of?(FiniteLine))
|
67
|
+
return distance_to_finite_line(target)
|
68
|
+
#with Plane
|
69
|
+
elsif(target.kind_of?(Plane))
|
70
|
+
return distance_to_plane(target)
|
71
|
+
end
|
72
|
+
Util3D.raise_argurment_error(target)
|
73
|
+
end
|
74
|
+
|
75
|
+
# [Input]
|
76
|
+
# _target_point_ should be Vector3.
|
77
|
+
# [Output]
|
78
|
+
# retrun projected point on plane as Vector3.
|
79
|
+
def project( target_point )
|
80
|
+
Util3D.check_arg_type(::Vector3, target_point)
|
81
|
+
distance, closest_point = self.distance( target_point )
|
82
|
+
return closest_point
|
83
|
+
end
|
84
|
+
private
|
85
|
+
def distance_to_point(target_point)
|
86
|
+
vector_QA = target_point - @base_point
|
87
|
+
distance = vector_QA.dot(@normal)
|
88
|
+
closest_point = target_point - @normal*distance
|
89
|
+
return distance.abs, closest_point
|
90
|
+
end
|
91
|
+
|
92
|
+
def distance_to_line(target_line)
|
93
|
+
inner_product_normal_and_line_vec = target_line.direction.dot(self.normal)
|
94
|
+
#parallel
|
95
|
+
if( inner_product_normal_and_line_vec.abs < @tolerance)
|
96
|
+
distance, closest_point = self.distance(target_line.base_point)
|
97
|
+
return distance, nil,nil
|
98
|
+
end
|
99
|
+
parameter = ( self.normal.dot(self.base_point) - self.normal.dot( target_line.base_point ) )/inner_product_normal_and_line_vec.to_f
|
100
|
+
intersect_point = target_line.point(parameter)
|
101
|
+
return 0.0, intersect_point, parameter
|
102
|
+
end
|
103
|
+
|
104
|
+
def distance_to_finite_line(target_finite_line)
|
105
|
+
target_infinite_line = Line.new(target_finite_line.start_point, target_finite_line.direction)
|
106
|
+
distance, intersect_point, parameter = self.distance(target_infinite_line)
|
107
|
+
point_on_line = intersect_point
|
108
|
+
point_on_plane = intersect_point
|
109
|
+
if(parameter != nil and (parameter < 0 or 1 < parameter))
|
110
|
+
parameter = [0, parameter].max
|
111
|
+
parameter = [1, parameter].min
|
112
|
+
point_on_line = target_finite_line.point(parameter)
|
113
|
+
distance, point_on_plane = self.distance(point_on_line)
|
114
|
+
end
|
115
|
+
return distance, point_on_plane, point_on_line, parameter
|
116
|
+
end
|
117
|
+
def distance_to_plane(target_plane)
|
118
|
+
line_vector = target_plane.normal.cross(self.normal)
|
119
|
+
if(target_plane.normal.parallel?(self.normal))
|
120
|
+
distance, point_on_plane = self.distance(target_plane.base_point)
|
121
|
+
return distance, nil
|
122
|
+
end
|
123
|
+
line_vector = line_vector.normalize()
|
124
|
+
tangent_vector_on_target_plane = line_vector.cross(target_plane.normal)
|
125
|
+
distance, intersect_point, parameter = self.distance(Line.new( target_plane.base_point, tangent_vector_on_target_plane))
|
126
|
+
intersect_line = Line.new(intersect_point, line_vector)
|
127
|
+
return 0, intersect_line
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
data/lib/polyline.rb
CHANGED
@@ -1,73 +1,73 @@
|
|
1
|
-
require 'gmath3D'
|
2
|
-
|
3
|
-
module GMath3D
|
4
|
-
#
|
5
|
-
# Polyline represents a closed or open polyline on 3D space.
|
6
|
-
#
|
7
|
-
class Polyline < Geom
|
8
|
-
public
|
9
|
-
attr_accessor :vertices
|
10
|
-
attr_accessor :is_open
|
11
|
-
|
12
|
-
include BoxAvailable
|
13
|
-
|
14
|
-
# [Input]
|
15
|
-
# _vertices_ should be Array of Vector3.
|
16
|
-
# [Output]
|
17
|
-
# return new instance of Polyline.
|
18
|
-
def initialize(vertices = [], is_open = true)
|
19
|
-
Util3D.check_arg_type(Array, vertices)
|
20
|
-
super()
|
21
|
-
@vertices = vertices
|
22
|
-
@is_open = is_open
|
23
|
-
end
|
24
|
-
|
25
|
-
def initialize_copy( original_obj )
|
26
|
-
@vertices = Array.new(original_obj.vertices.size)
|
27
|
-
for i in 0..@vertices.size-1
|
28
|
-
@vertices[i] = original_obj.vertices[i].dup
|
29
|
-
end
|
30
|
-
@is_open = original_obj.is_open
|
31
|
-
end
|
32
|
-
|
33
|
-
# [Input]
|
34
|
-
# _rhs_ is Polyline.
|
35
|
-
# [Output]
|
36
|
-
# return true if rhs equals myself.
|
37
|
-
def ==(rhs)
|
38
|
-
return false if rhs == nil
|
39
|
-
return false if( !rhs.kind_of?(Polyline) )
|
40
|
-
return false if( self.is_open != rhs.is_open )
|
41
|
-
return false if(@vertices.size != rhs.vertices.size)
|
42
|
-
for i in 0..(@vertices.size-1)
|
43
|
-
return false if( self.vertices[i] != rhs.vertices[i])
|
44
|
-
end
|
45
|
-
return true
|
46
|
-
end
|
47
|
-
|
48
|
-
def to_s
|
49
|
-
str = "Polyline["
|
50
|
-
vertices.each do |vertex|
|
51
|
-
str += vertex.to_element_s + ", "
|
52
|
-
end
|
53
|
-
str.slice!(str.length - 2, 2) if(vertices.size > 0)
|
54
|
-
str += "] "
|
55
|
-
str += "open" if(@is_open)
|
56
|
-
str += "closed" if(!@is_open)
|
57
|
-
return str
|
58
|
-
end
|
59
|
-
|
60
|
-
# [Output]
|
61
|
-
# return center point as Vector3.
|
62
|
-
def center
|
63
|
-
center = Vector3.new()
|
64
|
-
@vertices.each do |vertex|
|
65
|
-
center += vertex
|
66
|
-
end
|
67
|
-
center /= @vertices.size
|
68
|
-
return center
|
69
|
-
end
|
70
|
-
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
1
|
+
require 'gmath3D'
|
2
|
+
|
3
|
+
module GMath3D
|
4
|
+
#
|
5
|
+
# Polyline represents a closed or open polyline on 3D space.
|
6
|
+
#
|
7
|
+
class Polyline < Geom
|
8
|
+
public
|
9
|
+
attr_accessor :vertices
|
10
|
+
attr_accessor :is_open
|
11
|
+
|
12
|
+
include BoxAvailable
|
13
|
+
|
14
|
+
# [Input]
|
15
|
+
# _vertices_ should be Array of Vector3.
|
16
|
+
# [Output]
|
17
|
+
# return new instance of Polyline.
|
18
|
+
def initialize(vertices = [], is_open = true)
|
19
|
+
Util3D.check_arg_type(Array, vertices)
|
20
|
+
super()
|
21
|
+
@vertices = vertices
|
22
|
+
@is_open = is_open
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize_copy( original_obj )
|
26
|
+
@vertices = Array.new(original_obj.vertices.size)
|
27
|
+
for i in 0..@vertices.size-1
|
28
|
+
@vertices[i] = original_obj.vertices[i].dup
|
29
|
+
end
|
30
|
+
@is_open = original_obj.is_open
|
31
|
+
end
|
32
|
+
|
33
|
+
# [Input]
|
34
|
+
# _rhs_ is Polyline.
|
35
|
+
# [Output]
|
36
|
+
# return true if rhs equals myself.
|
37
|
+
def ==(rhs)
|
38
|
+
return false if rhs == nil
|
39
|
+
return false if( !rhs.kind_of?(Polyline) )
|
40
|
+
return false if( self.is_open != rhs.is_open )
|
41
|
+
return false if(@vertices.size != rhs.vertices.size)
|
42
|
+
for i in 0..(@vertices.size-1)
|
43
|
+
return false if( self.vertices[i] != rhs.vertices[i])
|
44
|
+
end
|
45
|
+
return true
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_s
|
49
|
+
str = "Polyline["
|
50
|
+
vertices.each do |vertex|
|
51
|
+
str += vertex.to_element_s + ", "
|
52
|
+
end
|
53
|
+
str.slice!(str.length - 2, 2) if(vertices.size > 0)
|
54
|
+
str += "] "
|
55
|
+
str += "open" if(@is_open)
|
56
|
+
str += "closed" if(!@is_open)
|
57
|
+
return str
|
58
|
+
end
|
59
|
+
|
60
|
+
# [Output]
|
61
|
+
# return center point as Vector3.
|
62
|
+
def center
|
63
|
+
center = Vector3.new()
|
64
|
+
@vertices.each do |vertex|
|
65
|
+
center += vertex
|
66
|
+
end
|
67
|
+
center /= @vertices.size
|
68
|
+
return center
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|