gmath3D 0.2.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/geom.rb CHANGED
@@ -1,20 +1,20 @@
1
- module GMath3D
2
-
3
- class Geom
4
- private
5
- @@default_tolerance = 1e-6
6
- @tolerance
7
-
8
- public
9
- attr_accessor :tolerance
10
-
11
- def initialize
12
- @tolerance = @@default_tolerance
13
- end
14
-
15
- def self.default_tolerance
16
- @@default_tolerance
17
- end
18
- end
19
-
20
- end
1
+ module GMath3D
2
+
3
+ class Geom
4
+ private
5
+ @@default_tolerance = 1e-6
6
+ @tolerance
7
+
8
+ public
9
+ attr_accessor :tolerance
10
+
11
+ def initialize
12
+ @tolerance = @@default_tolerance
13
+ end
14
+
15
+ def self.default_tolerance
16
+ @@default_tolerance
17
+ end
18
+ end
19
+
20
+ end
data/lib/gmath3D.rb CHANGED
@@ -1,22 +1,22 @@
1
- $LOAD_PATH.unshift(File.dirname(__FILE__))
2
-
3
- require 'util'
4
- require 'ext'
5
-
6
- require 'geom'
7
- require 'quat'
8
-
9
- require 'vector3'
10
-
11
- require 'line'
12
- require 'finite_line'
13
- require 'ellipse'
14
-
15
- require 'plane'
16
- require 'rectangle'
17
- require 'triangle'
18
- require 'box'
19
-
20
- require 'polyline'
21
-
22
- require 'tri_mesh'
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+
3
+ require 'util'
4
+ require 'ext'
5
+
6
+ require 'geom'
7
+ require 'quat'
8
+
9
+ require 'vector3'
10
+
11
+ require 'line'
12
+ require 'finite_line'
13
+ require 'ellipse'
14
+
15
+ require 'plane'
16
+ require 'rectangle'
17
+ require 'triangle'
18
+ require 'box'
19
+
20
+ require 'polyline'
21
+
22
+ require 'tri_mesh'
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
+