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/.document
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
# Add dependencies to develop your gem here.
|
7
|
+
# Include everything needed to run rake, tests, features, etc.
|
8
|
+
group :development do
|
9
|
+
gem "bundler", "~> 1.0.0"
|
10
|
+
gem "jeweler", "~> 1.6.4"
|
11
|
+
end
|
data/Gemfile.lock
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Toshiyasu Shimizu
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
= gmath3D
|
2
|
+
|
3
|
+
This library defines 3D geometric elements(point, line, plane etc..). It can get two(or more) elements relation, like distance between two elements.
|
4
|
+
|
5
|
+
== Class list in gmath3D
|
6
|
+
* Vector3 class signifies point and vector in 3D.
|
7
|
+
* Line class signifies inifinite line in 3D.
|
8
|
+
* FiniteLine class signifies finite line in 3D.
|
9
|
+
* Plane class signifies inifinite plane in 3D.
|
10
|
+
* Rectangle class signifies finite plane that has 4 edges in 3.
|
11
|
+
* Triangle class signifies finite plane that has 3 edges in 3.
|
12
|
+
* Box class signifies axially aligned box.
|
13
|
+
* Geom class is parent class of all 3D elements.
|
14
|
+
|
15
|
+
== Copyright
|
16
|
+
|
17
|
+
Copyright (c) 2011 Toshiyasu Shimizu. See LICENSE.txt for
|
18
|
+
further details.
|
19
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "gmath3D"
|
18
|
+
gem.homepage = "http://github.com/toshi0328/gmath3D"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Geometric elements in 3D}
|
21
|
+
gem.description = %Q{This library defines 3D geometric elements(point, line, plane etc..). It can get two(or more) elements relation, like distance between two elements.}
|
22
|
+
gem.email = "toshi0328@gmail.com"
|
23
|
+
gem.authors = ["Toshiyasu Shimizu"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rake/testtask'
|
29
|
+
Rake::TestTask.new(:test) do |test|
|
30
|
+
test.libs << 'lib' << 'test'
|
31
|
+
test.pattern = 'test/**/test_*.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
|
35
|
+
task :default => :test
|
36
|
+
|
37
|
+
require 'rake/rdoctask'
|
38
|
+
Rake::RDocTask.new do |rdoc|
|
39
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
40
|
+
|
41
|
+
rdoc.rdoc_dir = 'rdoc'
|
42
|
+
rdoc.title = "gmath3D #{version}"
|
43
|
+
rdoc.rdoc_files.include('README*')
|
44
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
45
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.1
|
data/gmath3D.gemspec
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{gmath3D}
|
8
|
+
s.version = "0.1.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Toshiyasu Shimizu"]
|
12
|
+
s.date = %q{2011-09-24}
|
13
|
+
s.description = %q{This library defines 3D geometric elements(point, line, plane etc..). It can get two(or more) elements relation, like distance between two elements.}
|
14
|
+
s.email = %q{toshi0328@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
"Gemfile",
|
22
|
+
"Gemfile.lock",
|
23
|
+
"LICENSE.txt",
|
24
|
+
"README.rdoc",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"gmath3D.gemspec",
|
28
|
+
"lib/box.rb",
|
29
|
+
"lib/finite_line.rb",
|
30
|
+
"lib/geom.rb",
|
31
|
+
"lib/gmath3D.rb",
|
32
|
+
"lib/line.rb",
|
33
|
+
"lib/plane.rb",
|
34
|
+
"lib/rectangle.rb",
|
35
|
+
"lib/triangle.rb",
|
36
|
+
"lib/util.rb",
|
37
|
+
"lib/vector3.rb",
|
38
|
+
"test/helper.rb",
|
39
|
+
"test/test_box.rb",
|
40
|
+
"test/test_finite_line.rb",
|
41
|
+
"test/test_geom.rb",
|
42
|
+
"test/test_gmath3D.rb",
|
43
|
+
"test/test_line.rb",
|
44
|
+
"test/test_plane.rb",
|
45
|
+
"test/test_rectangle.rb",
|
46
|
+
"test/test_triangle.rb",
|
47
|
+
"test/test_util.rb",
|
48
|
+
"test/test_vector3.rb"
|
49
|
+
]
|
50
|
+
s.homepage = %q{http://github.com/toshi0328/gmath3D}
|
51
|
+
s.licenses = ["MIT"]
|
52
|
+
s.require_paths = ["lib"]
|
53
|
+
s.rubygems_version = %q{1.6.2}
|
54
|
+
s.summary = %q{Geometric elements in 3D}
|
55
|
+
|
56
|
+
if s.respond_to? :specification_version then
|
57
|
+
s.specification_version = 3
|
58
|
+
|
59
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
60
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
61
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
62
|
+
else
|
63
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
64
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
65
|
+
end
|
66
|
+
else
|
67
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
68
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
data/lib/box.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'gmath3D'
|
2
|
+
|
3
|
+
module GMath3D
|
4
|
+
class Box < Geom
|
5
|
+
public
|
6
|
+
attr_accessor :min_point
|
7
|
+
attr_accessor :max_point
|
8
|
+
|
9
|
+
def initialize(point1 = Vector3.new(0,0,0), point2 = Vector3.new(1,1,1))
|
10
|
+
Util.check_arg_type(Vector3, point1)
|
11
|
+
Util.check_arg_type(Vector3, point2)
|
12
|
+
super()
|
13
|
+
@min_point = Vector3.new();
|
14
|
+
@max_point = Vector3.new();
|
15
|
+
@min_point.x = [ point1.x, point2.x ].min
|
16
|
+
@min_point.y = [ point1.y, point2.y ].min
|
17
|
+
@min_point.z = [ point1.z, point2.z ].min
|
18
|
+
@max_point.x = [ point1.x, point2.x ].max
|
19
|
+
@max_point.y = [ point1.y, point2.y ].max
|
20
|
+
@max_point.z = [ point1.z, point2.z ].max
|
21
|
+
end
|
22
|
+
|
23
|
+
def ==(rhs)
|
24
|
+
equals_inner(rhs)
|
25
|
+
end
|
26
|
+
def +(rhs)
|
27
|
+
add(rhs)
|
28
|
+
end
|
29
|
+
|
30
|
+
def center
|
31
|
+
return (@min_point + @max_point) * 0.5
|
32
|
+
end
|
33
|
+
|
34
|
+
def length
|
35
|
+
return max_point.x - min_point.x, max_point.y - min_point.y, max_point.z - min_point.z
|
36
|
+
end
|
37
|
+
|
38
|
+
def volume
|
39
|
+
width, height, depth = self.length
|
40
|
+
return width*height*depth
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
def equals_inner(rhs)
|
45
|
+
return false if( !rhs.kind_of?(Box) )
|
46
|
+
return false if(self.min_point != rhs.min_point)
|
47
|
+
return false if(self.max_point != rhs.max_point)
|
48
|
+
true
|
49
|
+
end
|
50
|
+
def add(rhs)
|
51
|
+
if( rhs.kind_of?(Vector3))
|
52
|
+
added_box = Box.new()
|
53
|
+
added_box.min_point.x = [ self.min_point.x, rhs.x ].min
|
54
|
+
added_box.min_point.y = [ self.min_point.y, rhs.y ].min
|
55
|
+
added_box.min_point.z = [ self.min_point.z, rhs.z ].min
|
56
|
+
added_box.max_point.x = [ self.max_point.x, rhs.x ].max
|
57
|
+
added_box.max_point.y = [ self.max_point.y, rhs.y ].max
|
58
|
+
added_box.max_point.z = [ self.max_point.z, rhs.z ].max
|
59
|
+
return added_box
|
60
|
+
elsif( rhs.kind_of?(Box))
|
61
|
+
min_max_point_ary = [rhs.min_point, rhs.max_point]
|
62
|
+
return self + min_max_point_ary
|
63
|
+
elsif(rhs.kind_of?(Array))
|
64
|
+
added_box = self;
|
65
|
+
rhs.each do |item|
|
66
|
+
added_box = added_box + item
|
67
|
+
end
|
68
|
+
return added_box
|
69
|
+
end
|
70
|
+
Util.raise_argurment_error(rhs)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
data/lib/finite_line.rb
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'gmath3D'
|
2
|
+
|
3
|
+
module GMath3D
|
4
|
+
class FiniteLine < Geom
|
5
|
+
public
|
6
|
+
attr_accessor :start_point
|
7
|
+
attr_accessor :end_point
|
8
|
+
|
9
|
+
def initialize(start_point_arg = Vector3.new(0.0,0.0,0.0), end_point_arg = Vector3.new(1.0,0.0,0.0))
|
10
|
+
Util.check_arg_type(Vector3, start_point_arg)
|
11
|
+
Util.check_arg_type(Vector3, end_point_arg)
|
12
|
+
super()
|
13
|
+
@start_point = start_point_arg
|
14
|
+
@end_point = end_point_arg
|
15
|
+
end
|
16
|
+
|
17
|
+
def direction
|
18
|
+
@end_point - @start_point
|
19
|
+
end
|
20
|
+
|
21
|
+
def point(parameter)
|
22
|
+
if(parameter < 0.0 or 1.0 < parameter)
|
23
|
+
return nil
|
24
|
+
else
|
25
|
+
return @start_point * (1.0 - parameter) + @end_point * parameter
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def length
|
30
|
+
@start_point.distance(@end_point)
|
31
|
+
end
|
32
|
+
|
33
|
+
def distance(target)
|
34
|
+
# with Point
|
35
|
+
if(target.kind_of?(Vector3))
|
36
|
+
return distance_to_point(target)
|
37
|
+
#with Line
|
38
|
+
elsif(target.kind_of?(Line))
|
39
|
+
return distance_to_line(target)
|
40
|
+
#widh Finite Line
|
41
|
+
elsif(target.kind_of?(FiniteLine))
|
42
|
+
return distance_to_finite_line(target)
|
43
|
+
end
|
44
|
+
Util.raise_argurment_error(target)
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.ary_distanc_to_point(finite_lines, target_point)
|
48
|
+
Util.check_arg_type(::Array, finite_lines)
|
49
|
+
Util.check_arg_type(Vector3, target_point)
|
50
|
+
distance_ary = Array.new(0)
|
51
|
+
points_ary = Array.new(0)
|
52
|
+
finite_lines.each do | item |
|
53
|
+
distance, point = item.distance(target_point)
|
54
|
+
distance_ary.push(distance);
|
55
|
+
points_ary.push(point)
|
56
|
+
end
|
57
|
+
distance = distance_ary.min
|
58
|
+
closest_point = points_ary[distance_ary.index(distance)]
|
59
|
+
return distance, closest_point
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
def distance_to_point(target)
|
64
|
+
# get distance using infinite line
|
65
|
+
infinite_line = Line.new(self.start_point, self.direction)
|
66
|
+
distance, closest_point, parameter = infinite_line.distance(target)
|
67
|
+
if(0.0 <= parameter and parameter <= 1.0)
|
68
|
+
return distance, closest_point, parameter
|
69
|
+
end
|
70
|
+
|
71
|
+
distance_to_start_point = @start_point.distance(target)
|
72
|
+
distance_to_end_point = @end_point.distance(target)
|
73
|
+
if(distance_to_start_point < distance_to_end_point)
|
74
|
+
distance = distance_to_start_point
|
75
|
+
closest_point = @start_point
|
76
|
+
parameter = 0.0
|
77
|
+
else
|
78
|
+
distance = distance_to_end_point
|
79
|
+
closest_point = @end_point
|
80
|
+
parameter = 1.0
|
81
|
+
end
|
82
|
+
return distance, closest_point, parameter
|
83
|
+
end
|
84
|
+
|
85
|
+
def distance_to_line(target_infinite_line)
|
86
|
+
self_infinite_line = Line.new(self.start_point, self.direction)
|
87
|
+
distance, point1, point2, parameter1, parameter2 = self_infinite_line.distance(target_infinite_line)
|
88
|
+
#parallel
|
89
|
+
return distance, nil, nil, nil, nil if( point1 == nil and point2 == nil)
|
90
|
+
#parameter is in range
|
91
|
+
return distance, point1, point2, parameter1, parameter2 if(0 < parameter1 and parameter1 < 1)
|
92
|
+
distance_to_start_point, closest_point_to_start_point, parameter_to_start_point =
|
93
|
+
target_infinite_line.distance(self.start_point)
|
94
|
+
distance_to_end_point, closest_point_to_end_point, parameter_to_end_point =
|
95
|
+
target_infinite_line.distance(self.end_point)
|
96
|
+
if(distance_to_start_point < distance_to_end_point)
|
97
|
+
return distance_to_start_point, self.start_point, closest_point_to_start_point, 0.0, parameter_to_start_point
|
98
|
+
else
|
99
|
+
return distance_to_end_point, self.end_point, closest_point_to_end_point, 1.0, parameter_to_end_point
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def distance_to_finite_line(target_finite_line)
|
104
|
+
line1 = Line.new(self.start_point, self.direction)
|
105
|
+
line2 = Line.new(target_finite_line.start_point, target_finite_line.direction)
|
106
|
+
distance, point_myself, point_target, parameter_myself, parameter_target = line1.distance( line2 )
|
107
|
+
if(point_myself == nil and point_target == nil)
|
108
|
+
#prallel or including case
|
109
|
+
point_pair = Array.new(4)
|
110
|
+
point_pair[0] = Array.new([self.start_point, target_finite_line.start_point, 0, 0])
|
111
|
+
point_pair[1] = Array.new([self.start_point, target_finite_line.end_point, 0,1])
|
112
|
+
point_pair[2] = Array.new([self.end_point, target_finite_line.start_point, 1,0])
|
113
|
+
point_pair[3] = Array.new([self.end_point, target_finite_line.end_point,1,1])
|
114
|
+
|
115
|
+
distance_ary = Array.new(0)
|
116
|
+
point_pair.each do |points|
|
117
|
+
distance_ary << points[0].distance(points[1])
|
118
|
+
end
|
119
|
+
distance_min = distance_ary.min
|
120
|
+
distance_min_ary = Array.new(0)
|
121
|
+
distance_min_index = nil
|
122
|
+
distance_ary.each do |item|
|
123
|
+
if( item - tolerance < distance_min )
|
124
|
+
distance_min_ary << item
|
125
|
+
distance_min_index = distance_ary.index(item)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
if( distance_min_ary.size == 1)
|
129
|
+
target_point_pair = point_pair[distance_min_index]
|
130
|
+
distance = target_point_pair[0].distance(target_point_pair[1])
|
131
|
+
return distance, target_point_pair[0], target_point_pair[1], target_point_pair[2], target_point_pair[3]
|
132
|
+
else
|
133
|
+
return distance, nil, nil, nil, nil
|
134
|
+
end
|
135
|
+
#out of range
|
136
|
+
elsif( parameter_myself < 0 or 1 < parameter_myself or parameter_target < 0 or 1 < parameter_target )
|
137
|
+
parameter_myself = [1, parameter_myself].min
|
138
|
+
parameter_myself = [0, parameter_myself].max
|
139
|
+
distance1, point_target, paramter_target_tmp = target_finite_line.distance(point_myself)
|
140
|
+
|
141
|
+
parameter_target = [1, parameter_target].min
|
142
|
+
parameter_target = [0, parameter_target].max
|
143
|
+
distance2, point_myself, parameter_myself_tmp = self.distance(point_target)
|
144
|
+
if(distance1 < distance2)
|
145
|
+
parameter_target = paramter_target_tmp
|
146
|
+
else
|
147
|
+
parameter_myself = parameter_myself_tmp
|
148
|
+
end
|
149
|
+
end
|
150
|
+
point_myself = line1.point(parameter_myself);
|
151
|
+
point_target = line2.point(parameter_target);
|
152
|
+
distance = point_myself.distance(point_target)
|
153
|
+
return distance, point_myself, point_target, parameter_myself, parameter_target
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
data/lib/geom.rb
ADDED
@@ -0,0 +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
|
data/lib/gmath3D.rb
ADDED
data/lib/line.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'gmath3D'
|
2
|
+
|
3
|
+
module GMath3D
|
4
|
+
class Line < Geom
|
5
|
+
public
|
6
|
+
attr_accessor :base_point
|
7
|
+
attr_accessor :direction
|
8
|
+
|
9
|
+
def initialize(point = Vector3.new(0.0,0.0,0.0), direction = Vector3.new(1.0,0.0,0.0))
|
10
|
+
Util.check_arg_type(Vector3, point)
|
11
|
+
Util.check_arg_type(Vector3, direction)
|
12
|
+
super()
|
13
|
+
@base_point = point
|
14
|
+
@direction = direction
|
15
|
+
end
|
16
|
+
|
17
|
+
def point(parameter)
|
18
|
+
Util.check_arg_type(::Numeric, parameter)
|
19
|
+
@base_point + @direction*parameter
|
20
|
+
end
|
21
|
+
|
22
|
+
def distance(target)
|
23
|
+
# with Point
|
24
|
+
if(target.kind_of?(Vector3))
|
25
|
+
return distance_to_point(target)
|
26
|
+
#with Line
|
27
|
+
elsif(target.kind_of?(Line))
|
28
|
+
return distance_to_line(target)
|
29
|
+
end
|
30
|
+
Util.raise_argurment_error(target)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def distance_to_point(target_point)
|
35
|
+
point_on_line1 = self.base_point
|
36
|
+
point_on_line2 = self.base_point + self.direction
|
37
|
+
|
38
|
+
vecAB = point_on_line2 - point_on_line1
|
39
|
+
vecAP = target_point - point_on_line1
|
40
|
+
vecAQ, parameter = vecAP.project_to(vecAB)
|
41
|
+
cross_point = point_on_line1 + vecAQ
|
42
|
+
vecPQ = vecAQ - vecAP
|
43
|
+
return vecPQ.length, cross_point, parameter
|
44
|
+
end
|
45
|
+
|
46
|
+
def distance_to_line(target_line)
|
47
|
+
if(self.direction.parallel?(target_line.direction)) then
|
48
|
+
distanceInfo = self.distance(target_line.base_point)
|
49
|
+
return distanceInfo[0], nil, nil, nil, nil
|
50
|
+
else
|
51
|
+
line1_point1 = self.base_point
|
52
|
+
line1_point2 = self.base_point + self.direction
|
53
|
+
line2_point1 = target_line.base_point
|
54
|
+
line2_point2 = target_line.base_point + target_line.direction
|
55
|
+
|
56
|
+
vec_da = line1_point2 - line1_point1
|
57
|
+
vec_db = line2_point2 - line2_point1
|
58
|
+
vec_ab = line2_point1 - line1_point1
|
59
|
+
|
60
|
+
abs_vec_db = vec_db.length*vec_db.length
|
61
|
+
abs_vec_da = vec_da.length*vec_da.length
|
62
|
+
|
63
|
+
delta = (abs_vec_da*abs_vec_db - vec_da.dot( vec_db )*vec_da.dot( vec_db ))
|
64
|
+
|
65
|
+
if( delta < self.tolerance )
|
66
|
+
# TODO ASSERT(false)
|
67
|
+
return nil
|
68
|
+
end
|
69
|
+
parameter1 = (abs_vec_db*vec_ab.dot(vec_da) - vec_da.dot( vec_db )*vec_ab.dot( vec_db ) ) / delta
|
70
|
+
parameter2 = (vec_da.dot( vec_db )*vec_ab.dot( vec_da ) - abs_vec_da*vec_ab.dot( vec_db ))/ delta
|
71
|
+
|
72
|
+
line1_closest_point = line1_point1 + vec_da*parameter1
|
73
|
+
line2_closest_point = line2_point1 + vec_db*parameter2
|
74
|
+
distance = line1_closest_point.distance( line2_closest_point )
|
75
|
+
return distance, line1_closest_point, line2_closest_point, parameter1, parameter2
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
data/lib/plane.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'gmath3D'
|
2
|
+
|
3
|
+
module GMath3D
|
4
|
+
class Plane < Geom
|
5
|
+
public
|
6
|
+
attr_accessor:base_point
|
7
|
+
attr_accessor:normal
|
8
|
+
|
9
|
+
def initialize(base_point_arg = Vector3.new(), normal_arg = Vector3.new(0,0,1))
|
10
|
+
Util.check_arg_type(::Vector3, normal_arg)
|
11
|
+
Util.check_arg_type(::Vector3, base_point_arg)
|
12
|
+
super()
|
13
|
+
@base_point = base_point_arg
|
14
|
+
@normal = normal_arg.normalize()
|
15
|
+
end
|
16
|
+
|
17
|
+
def distance(target)
|
18
|
+
# with Point
|
19
|
+
if(target.kind_of?(Vector3))
|
20
|
+
return distance_to_point(target)
|
21
|
+
#with Line
|
22
|
+
elsif(target.kind_of?(Line))
|
23
|
+
return distance_to_line(target)
|
24
|
+
#with FiniteLine
|
25
|
+
elsif(target.kind_of?(FiniteLine))
|
26
|
+
return distance_to_finite_line(target)
|
27
|
+
#with Plane
|
28
|
+
elsif(target.kind_of?(Plane))
|
29
|
+
return distance_to_plane(target)
|
30
|
+
end
|
31
|
+
Util.raise_argurment_error(target)
|
32
|
+
end
|
33
|
+
|
34
|
+
def project( target_point )
|
35
|
+
Util.check_arg_type(::Vector3, target_point)
|
36
|
+
distance, closest_point = self.distance( target_point )
|
37
|
+
return closest_point
|
38
|
+
end
|
39
|
+
private
|
40
|
+
def distance_to_point(target_point)
|
41
|
+
vector_QA = target_point - @base_point
|
42
|
+
distance = vector_QA.dot(@normal)
|
43
|
+
closest_point = target_point - @normal*distance
|
44
|
+
return distance.abs, closest_point
|
45
|
+
end
|
46
|
+
|
47
|
+
def distance_to_line(target_line)
|
48
|
+
inner_product_normal_and_line_vec = target_line.direction.dot(self.normal)
|
49
|
+
#parallel
|
50
|
+
if( inner_product_normal_and_line_vec.abs < @tolerance)
|
51
|
+
distance, closest_point = self.distance(target_line.base_point)
|
52
|
+
return distance, nil,nil
|
53
|
+
end
|
54
|
+
parameter = ( self.normal.dot(self.base_point) - self.normal.dot( target_line.base_point ) )/inner_product_normal_and_line_vec.to_f
|
55
|
+
intersect_point = target_line.point(parameter)
|
56
|
+
return 0.0, intersect_point, parameter
|
57
|
+
end
|
58
|
+
|
59
|
+
def distance_to_finite_line(target_finite_line)
|
60
|
+
target_infinite_line = Line.new(target_finite_line.start_point, target_finite_line.direction)
|
61
|
+
distance, intersect_point, parameter = self.distance(target_infinite_line)
|
62
|
+
point_on_line = intersect_point
|
63
|
+
point_on_plane = intersect_point
|
64
|
+
if(parameter != nil and (parameter < 0 or 1 < parameter))
|
65
|
+
parameter = [0, parameter].max
|
66
|
+
parameter = [1, parameter].min
|
67
|
+
point_on_line = target_finite_line.point(parameter)
|
68
|
+
distance, point_on_plane = self.distance(point_on_line)
|
69
|
+
end
|
70
|
+
return distance, point_on_plane, point_on_line, parameter
|
71
|
+
end
|
72
|
+
def distance_to_plane(target_plane)
|
73
|
+
line_vector = target_plane.normal.cross(self.normal)
|
74
|
+
if(target_plane.normal.parallel?(self.normal))
|
75
|
+
distance, point_on_plane = self.distance(target_plane.base_point)
|
76
|
+
return distance, nil
|
77
|
+
end
|
78
|
+
line_vector = line_vector.normalize()
|
79
|
+
tangent_vector_on_target_plane = line_vector.cross(target_plane.normal)
|
80
|
+
distance, intersect_point, parameter = self.distance(Line.new( target_plane.base_point, tangent_vector_on_target_plane))
|
81
|
+
intersect_line = Line.new(intersect_point, line_vector)
|
82
|
+
return 0, intersect_line
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|