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/.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
|
+
|