geo-triangle 0.0.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/.rspec +1 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +28 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +71 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/lib/geo-triangle.rb +60 -0
- data/lib/geo_triangle_ext/circum_center.rb +84 -0
- data/lib/geo_triangle_ext/linear_function.rb +77 -0
- data/lib/gravity_center.rb +75 -0
- data/spec/geo-triangle_spec.rb +130 -0
- data/spec/geo_triangle_ext/circum_center_spec.rb +178 -0
- data/spec/geo_triangle_ext/linear_function_spec.rb +97 -0
- data/spec/gravity_center_spec.rb +60 -0
- data/spec/spec_helper.rb +12 -0
- metadata +119 -0
data/.document
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
@@ -0,0 +1,13 @@
|
|
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 "rspec", "~> 2.3.0"
|
10
|
+
gem "bundler", "~> 1.0.0"
|
11
|
+
gem "jeweler", "~> 1.6.0"
|
12
|
+
gem "rcov", ">= 0"
|
13
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
diff-lcs (1.1.2)
|
5
|
+
git (1.2.5)
|
6
|
+
jeweler (1.6.0)
|
7
|
+
bundler (~> 1.0.0)
|
8
|
+
git (>= 1.2.5)
|
9
|
+
rake
|
10
|
+
rake (0.8.7)
|
11
|
+
rcov (0.9.9)
|
12
|
+
rspec (2.3.0)
|
13
|
+
rspec-core (~> 2.3.0)
|
14
|
+
rspec-expectations (~> 2.3.0)
|
15
|
+
rspec-mocks (~> 2.3.0)
|
16
|
+
rspec-core (2.3.1)
|
17
|
+
rspec-expectations (2.3.0)
|
18
|
+
diff-lcs (~> 1.1.2)
|
19
|
+
rspec-mocks (2.3.0)
|
20
|
+
|
21
|
+
PLATFORMS
|
22
|
+
ruby
|
23
|
+
|
24
|
+
DEPENDENCIES
|
25
|
+
bundler (~> 1.0.0)
|
26
|
+
jeweler (~> 1.6.0)
|
27
|
+
rcov
|
28
|
+
rspec (~> 2.3.0)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 parrot-studio
|
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,71 @@
|
|
1
|
+
= geo-triangle
|
2
|
+
|
3
|
+
== Introduction
|
4
|
+
|
5
|
+
Author:: parrot_studio < parrot at users.sourceforge.jp >
|
6
|
+
License:: The MIT License
|
7
|
+
|
8
|
+
三点の座標から中心(重心)を求める。
|
9
|
+
|
10
|
+
あくまで緯度経度を数値的に処理しているだけで、距離の補正等は考慮していない。
|
11
|
+
そのため、あまりに離れすぎた三点を指定すると、値が妥当でない場合があり得る。
|
12
|
+
|
13
|
+
== Install
|
14
|
+
gem install geo-triangle
|
15
|
+
|
16
|
+
== Usage
|
17
|
+
# require 'rubygems' # if ruby 1.8.x
|
18
|
+
require 'geo-triangle'
|
19
|
+
|
20
|
+
# 緯度(lat), 経度(lon)の組み合わせを3つ渡す
|
21
|
+
GeoTriangle.center(
|
22
|
+
[36.383304,139.073632], [36.391026,139.075107], [36.378536,139.046445]) #=> [36.384289, 139.065061]
|
23
|
+
|
24
|
+
# 順序が正しければ引数は適当でもいい
|
25
|
+
GeoTriangle.center(
|
26
|
+
36.383304,139.073632,36.391026,139.075107,36.378536,139.046445)
|
27
|
+
|
28
|
+
# newしてから構築するやり方
|
29
|
+
gt1 = GeoTriangle.new
|
30
|
+
gt1.set_coordinate([36.383304,139.073632])
|
31
|
+
gt1.set_coordinate([36.391026,139.075107])
|
32
|
+
gt1.set_coordinate([36.378536,139.046445])
|
33
|
+
gt1.center #=> [36.384289, 139.065061]
|
34
|
+
|
35
|
+
# 4個以上は無視される
|
36
|
+
gt2 = GeoTriangle.new
|
37
|
+
gt2.set_coordinate([36.383304,139.073632])
|
38
|
+
gt2.set_coordinate([36.391026,139.075107])
|
39
|
+
gt2.set_coordinate([36.378536,139.046445])
|
40
|
+
gt2.set_coordinate([37.378536,136.046445]) # 4つ目以降は無視
|
41
|
+
gt2.center #=> [36.384289, 139.065061]
|
42
|
+
|
43
|
+
# 同じ座標はまとめられる
|
44
|
+
gt3 = GeoTriangle.new
|
45
|
+
gt3.set_coordinate([36.383304,139.073632])
|
46
|
+
gt3.set_coordinate([36.391026,139.075107])
|
47
|
+
gt3.set_coordinate([36.391026,139.075107]) # 上と同じ座標
|
48
|
+
# 座標が2つと見なされ、座標の数が足りないのでnilを返す
|
49
|
+
gt3.center #=> nil
|
50
|
+
|
51
|
+
== Extra Module
|
52
|
+
# require 'rubygems' # if 1.8.x
|
53
|
+
require 'geo-triangle'
|
54
|
+
|
55
|
+
# 重心ではなく外心を求めたい場合
|
56
|
+
cc = GeoTriangleExt::CircumCenter.create([0,4],[2,0],[5,6])
|
57
|
+
cc.center #=> [2.333333, 3.333333]
|
58
|
+
|
59
|
+
# 鈍角三角形の場合、外心は三角形の外になるため、実装はしたが使えない
|
60
|
+
|
61
|
+
== Release Note
|
62
|
+
|
63
|
+
=== ver 0.0.1
|
64
|
+
|
65
|
+
* release for test
|
66
|
+
|
67
|
+
== Copyright
|
68
|
+
|
69
|
+
Copyright (c) 2011 parrot-studio. See LICENSE.txt for
|
70
|
+
further details.
|
71
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,50 @@
|
|
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 = "geo-triangle"
|
18
|
+
gem.homepage = "http://github.com/parrot-studio/geo-triangle"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{calculate geo-triangle's gravity center}
|
21
|
+
gem.description = %Q{calculate center of 3 geo-coordinates(lat, lon)}
|
22
|
+
gem.email = "parrot@users.sourceforge.jp"
|
23
|
+
gem.authors = ["parrot-studio"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rspec/core'
|
29
|
+
require 'rspec/core/rake_task'
|
30
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
31
|
+
spec.rspec_opts = ["-c", "-r ./spec/spec_helper.rb"]
|
32
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
33
|
+
end
|
34
|
+
|
35
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
36
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
37
|
+
spec.rcov = true
|
38
|
+
end
|
39
|
+
|
40
|
+
task :default => :spec
|
41
|
+
|
42
|
+
require 'rake/rdoctask'
|
43
|
+
Rake::RDocTask.new do |rdoc|
|
44
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
45
|
+
|
46
|
+
rdoc.rdoc_dir = 'rdoc'
|
47
|
+
rdoc.title = "geo-triangle #{version}"
|
48
|
+
rdoc.rdoc_files.include('README*')
|
49
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
50
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/lib/geo-triangle.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'bigdecimal'
|
3
|
+
require 'gravity_center'
|
4
|
+
require 'geo_triangle_ext/linear_function'
|
5
|
+
require 'geo_triangle_ext/circum_center'
|
6
|
+
|
7
|
+
class GeoTriangle
|
8
|
+
|
9
|
+
class << self
|
10
|
+
|
11
|
+
def center(*val)
|
12
|
+
gt = self.new
|
13
|
+
v = [val].flatten
|
14
|
+
gt.set_coordinate(v[0], v[1])
|
15
|
+
gt.set_coordinate(v[2], v[3])
|
16
|
+
gt.set_coordinate(v[4], v[5])
|
17
|
+
gt.center
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def exist?(lat, lon)
|
23
|
+
return false unless lat
|
24
|
+
return false unless lon
|
25
|
+
return false if lat.abs > 90.0
|
26
|
+
return false if lon.abs > 180.0
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_coordinate(*val)
|
31
|
+
v = [val].flatten
|
32
|
+
lat = v[0]
|
33
|
+
lon = v[1]
|
34
|
+
coordinates << [lat, lon] if exist?(lat, lon)
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
def coordinates
|
39
|
+
@coordinates ||= []
|
40
|
+
@coordinates = @coordinates.uniq
|
41
|
+
@coordinates = @coordinates.take(3) if @coordinates.size > 3
|
42
|
+
@coordinates
|
43
|
+
end
|
44
|
+
|
45
|
+
def valid_coordinates?
|
46
|
+
return false unless coordinates.size == 3
|
47
|
+
return false unless coordinates.all?{|c| c.size == 2}
|
48
|
+
true
|
49
|
+
end
|
50
|
+
|
51
|
+
def center
|
52
|
+
return unless valid_coordinates?
|
53
|
+
gc = GravityCenter.create(*coordinates)
|
54
|
+
lat = gc.center_x.round(6).to_f
|
55
|
+
lon = gc.center_y.round(6).to_f
|
56
|
+
exist?(lat, lon) ? [lat, lon] : nil
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
module GeoTriangleExt
|
3
|
+
|
4
|
+
class CircumCenter
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def create(*co)
|
9
|
+
cc = self.new
|
10
|
+
co.take(3).each{|c| cc.coordinates << c}
|
11
|
+
cc
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
def set_coordinate(x, y)
|
17
|
+
coordinates << [x, y]
|
18
|
+
end
|
19
|
+
|
20
|
+
def coordinates
|
21
|
+
@coordinates ||= []
|
22
|
+
@coordinates = @coordinates.uniq
|
23
|
+
@coordinates = @coordinates.take(3) if @coordinates.size > 3
|
24
|
+
@coordinates
|
25
|
+
end
|
26
|
+
|
27
|
+
def valid_coordinates?
|
28
|
+
return false unless coordinates.size == 3
|
29
|
+
return false unless coordinates.all?{|c| c.size == 2}
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
def functions
|
34
|
+
@functions ||= create_functions
|
35
|
+
@functions
|
36
|
+
end
|
37
|
+
|
38
|
+
def valid_functions?
|
39
|
+
return false if functions.size < 2
|
40
|
+
return false if functions.combination(2).any?{|f1, f2|
|
41
|
+
f1.orthogonal_slope == f2.orthogonal_slope}
|
42
|
+
true
|
43
|
+
end
|
44
|
+
|
45
|
+
def center
|
46
|
+
return unless valid_functions?
|
47
|
+
@center_point ||= calc_center
|
48
|
+
@center_point
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def create_functions
|
54
|
+
return [] unless valid_coordinates?
|
55
|
+
ret = []
|
56
|
+
coordinates.combination(2) do |a, b|
|
57
|
+
f = LinearFunction.create(*([a, b].flatten))
|
58
|
+
next unless f
|
59
|
+
ret << f if f.valid?
|
60
|
+
end
|
61
|
+
ret
|
62
|
+
end
|
63
|
+
|
64
|
+
def calc_center
|
65
|
+
return unless valid_functions?
|
66
|
+
|
67
|
+
l1 = functions.first
|
68
|
+
l2 = functions.last
|
69
|
+
|
70
|
+
a1 = l1.orthogonal_slope
|
71
|
+
b1 = l1.orthogonal_intercept
|
72
|
+
a2 = l2.orthogonal_slope
|
73
|
+
b2 = l2.orthogonal_intercept
|
74
|
+
|
75
|
+
x = (b2 - b1) / (a1 - a2)
|
76
|
+
y = (a1 * b2 - b1 * a2) / (a1 - a2)
|
77
|
+
|
78
|
+
[x, y]
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
module GeoTriangleExt
|
3
|
+
|
4
|
+
class LinearFunction
|
5
|
+
|
6
|
+
attr_writer :ax, :ay, :bx, :by
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
def create(ax, ay, bx, by)
|
11
|
+
lf = self.new
|
12
|
+
lf.ax = ax
|
13
|
+
lf.ay = ay
|
14
|
+
lf.bx = bx
|
15
|
+
lf.by = by
|
16
|
+
lf
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def ax
|
22
|
+
@bax ||= BigDecimal(@ax.to_s)
|
23
|
+
@bax
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
def ay
|
28
|
+
@bay ||= BigDecimal(@ay.to_s)
|
29
|
+
@bay
|
30
|
+
end
|
31
|
+
|
32
|
+
def bx
|
33
|
+
@bbx ||= BigDecimal(@bx.to_s)
|
34
|
+
@bbx
|
35
|
+
end
|
36
|
+
|
37
|
+
def by
|
38
|
+
@bby ||= BigDecimal(@by.to_s)
|
39
|
+
@bby
|
40
|
+
end
|
41
|
+
|
42
|
+
def valid?
|
43
|
+
return false if ax == bx
|
44
|
+
return false if ay == by
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
def middle_point
|
49
|
+
x = (ax + bx) / 2.0
|
50
|
+
y = (ay + by) / 2.0
|
51
|
+
[x, y]
|
52
|
+
end
|
53
|
+
|
54
|
+
def slope
|
55
|
+
return unless valid?
|
56
|
+
(ay - by) / (ax - bx)
|
57
|
+
end
|
58
|
+
|
59
|
+
def intercept
|
60
|
+
return unless valid?
|
61
|
+
(ax * by - ay * bx) / (ax - bx)
|
62
|
+
end
|
63
|
+
|
64
|
+
def orthogonal_slope
|
65
|
+
return unless valid?
|
66
|
+
(bx - ax) / (ay - by)
|
67
|
+
end
|
68
|
+
|
69
|
+
def orthogonal_intercept
|
70
|
+
return unless valid?
|
71
|
+
(ax*ax + ay*ay - bx*bx - by*by) / (2 * (ay - by))
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'bigdecimal'
|
3
|
+
|
4
|
+
class GravityCenter
|
5
|
+
|
6
|
+
attr_reader :x1, :y1, :x2, :y2, :x3, :y3
|
7
|
+
|
8
|
+
def self.create(*val)
|
9
|
+
gc = self.new
|
10
|
+
gc.instance_eval do
|
11
|
+
v = [val].flatten
|
12
|
+
@x1 = BigDecimal(v[0].to_s)
|
13
|
+
@y1 = BigDecimal(v[1].to_s)
|
14
|
+
@x2 = BigDecimal(v[2].to_s)
|
15
|
+
@y2 = BigDecimal(v[3].to_s)
|
16
|
+
@x3 = BigDecimal(v[4].to_s)
|
17
|
+
@y3 = BigDecimal(v[5].to_s)
|
18
|
+
end
|
19
|
+
gc
|
20
|
+
end
|
21
|
+
|
22
|
+
def sx1
|
23
|
+
@sx1 ||= x1 - x3
|
24
|
+
@sx1
|
25
|
+
end
|
26
|
+
|
27
|
+
def sy1
|
28
|
+
@sy1 ||= y1 - y3
|
29
|
+
@sy1
|
30
|
+
end
|
31
|
+
|
32
|
+
def sx2
|
33
|
+
@sx2 ||= x2 - x3
|
34
|
+
@sx2
|
35
|
+
end
|
36
|
+
|
37
|
+
def sy2
|
38
|
+
@sy2 ||= y2 - y3
|
39
|
+
@sy2
|
40
|
+
end
|
41
|
+
|
42
|
+
def center_sx
|
43
|
+
@center_sx ||= calc_center_sx
|
44
|
+
@center_sx
|
45
|
+
end
|
46
|
+
|
47
|
+
def center_x
|
48
|
+
center_sx + x3
|
49
|
+
end
|
50
|
+
|
51
|
+
def center_sy
|
52
|
+
@center_sy ||= calc_center_sy
|
53
|
+
@center_sy
|
54
|
+
end
|
55
|
+
|
56
|
+
def center_y
|
57
|
+
center_sy + y3
|
58
|
+
end
|
59
|
+
|
60
|
+
def center
|
61
|
+
[center_x, center_y]
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def calc_center_sx
|
67
|
+
(sx1 + sx2) / 3
|
68
|
+
end
|
69
|
+
|
70
|
+
def calc_center_sy
|
71
|
+
(sy1 + sy2) / 3
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
describe GeoTriangle do
|
3
|
+
|
4
|
+
describe "#exist?" do
|
5
|
+
|
6
|
+
before do
|
7
|
+
@gt = GeoTriangle.new
|
8
|
+
end
|
9
|
+
|
10
|
+
context "lat or lon is nil" do
|
11
|
+
it {@gt.exist?(40.2, nil).should be_false}
|
12
|
+
it {@gt.exist?(nil, 135.0).should be_false}
|
13
|
+
end
|
14
|
+
|
15
|
+
context "over value" do
|
16
|
+
it {@gt.exist?(90.1, 135.0).should be_false}
|
17
|
+
it {@gt.exist?(42.0, 180.1).should be_false}
|
18
|
+
end
|
19
|
+
|
20
|
+
context "valid lat and lon" do
|
21
|
+
it {@gt.exist?(36.383304, 139.073632).should be_true}
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#set_coordinate" do
|
27
|
+
|
28
|
+
before do
|
29
|
+
@gt = GeoTriangle.new
|
30
|
+
end
|
31
|
+
|
32
|
+
context "exist coordinate" do
|
33
|
+
before do
|
34
|
+
@gt.set_coordinate([36.383304, 139.073632])
|
35
|
+
@gt.set_coordinate(36.391026, 139.075107)
|
36
|
+
end
|
37
|
+
it {@gt.coordinates.should == [[36.383304, 139.073632], [36.391026, 139.075107]]}
|
38
|
+
end
|
39
|
+
|
40
|
+
context "not exist coordinate" do
|
41
|
+
before do
|
42
|
+
@gt.set_coordinate([136.383304, 139.073632])
|
43
|
+
@gt.set_coordinate(36.391026, 239.075107)
|
44
|
+
end
|
45
|
+
it {@gt.coordinates.should be_empty}
|
46
|
+
end
|
47
|
+
|
48
|
+
context "not coordinate pair" do
|
49
|
+
before do
|
50
|
+
@gt.set_coordinate(36.383304)
|
51
|
+
end
|
52
|
+
it {@gt.coordinates.should be_empty}
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#valid_coordinates?" do
|
58
|
+
|
59
|
+
before do
|
60
|
+
@gt = GeoTriangle.new
|
61
|
+
end
|
62
|
+
|
63
|
+
context "coordinates size not enough" do
|
64
|
+
before do
|
65
|
+
@gt.set_coordinate([36.383304, 139.073632])
|
66
|
+
@gt.set_coordinate(36.391026, 139.075107)
|
67
|
+
end
|
68
|
+
it {@gt.coordinates.size.should == 2}
|
69
|
+
it {@gt.valid_coordinates?.should be_false}
|
70
|
+
end
|
71
|
+
|
72
|
+
context "invalid coordinate format" do
|
73
|
+
before do
|
74
|
+
@gt.set_coordinate([36.383304, 139.073632])
|
75
|
+
@gt.set_coordinate(36.391026, 139.075107)
|
76
|
+
@gt.coordinates << [135.0]
|
77
|
+
end
|
78
|
+
it {@gt.coordinates.size.should == 3}
|
79
|
+
it {@gt.valid_coordinates?.should be_false}
|
80
|
+
end
|
81
|
+
|
82
|
+
context "valid coordinates" do
|
83
|
+
before do
|
84
|
+
@gt.set_coordinate([36.383304,139.073632])
|
85
|
+
@gt.set_coordinate([36.391026,139.075107])
|
86
|
+
@gt.set_coordinate([36.378536,139.046445])
|
87
|
+
@gt.set_coordinate([37.378536,138.046445])
|
88
|
+
end
|
89
|
+
it {@gt.coordinates.size.should == 3}
|
90
|
+
it {@gt.valid_coordinates?.should be_true}
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "#center" do
|
96
|
+
|
97
|
+
before do
|
98
|
+
@gt = GeoTriangle.new
|
99
|
+
end
|
100
|
+
|
101
|
+
context "valid coordinates center" do
|
102
|
+
before do
|
103
|
+
@gt.set_coordinate([36.383304,139.073632])
|
104
|
+
@gt.set_coordinate([36.391026,139.075107])
|
105
|
+
@gt.set_coordinate([36.378536,139.046445])
|
106
|
+
end
|
107
|
+
it {@gt.center.should == [36.384289, 139.065061]}
|
108
|
+
end
|
109
|
+
|
110
|
+
context "invalid coordinates" do
|
111
|
+
before do
|
112
|
+
@gt.set_coordinate([36.383304,139.073632])
|
113
|
+
@gt.set_coordinate([36.391026,139.075107])
|
114
|
+
@gt.set_coordinate([36.391026,139.075107])
|
115
|
+
end
|
116
|
+
it {@gt.coordinates.size.should == 2}
|
117
|
+
it {@gt.valid_coordinates?.should be_false}
|
118
|
+
it {@gt.center.should be_nil}
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
describe ".center" do
|
124
|
+
subject {GeoTriangle.center(
|
125
|
+
[36.383304,139.073632], [36.391026,139.075107], [36.378536,139.046445])}
|
126
|
+
it {should == [36.384289, 139.065061]}
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
@@ -0,0 +1,178 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
describe GeoTriangleExt::CircumCenter do
|
3
|
+
|
4
|
+
describe "#set_coordinate" do
|
5
|
+
before do
|
6
|
+
@cc = GeoTriangleExt::CircumCenter.new
|
7
|
+
@cc.set_coordinate(1, 2)
|
8
|
+
end
|
9
|
+
it {@cc.coordinates.should == [[1,2]]}
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#coordinates" do
|
13
|
+
|
14
|
+
context "default" do
|
15
|
+
it {GeoTriangleExt::CircumCenter.new.coordinates.should be_empty}
|
16
|
+
end
|
17
|
+
|
18
|
+
context "has only 3 coordinates" do
|
19
|
+
before do
|
20
|
+
@cc = GeoTriangleExt::CircumCenter.new
|
21
|
+
@cc.set_coordinate(1, 2)
|
22
|
+
@cc.set_coordinate(3, 4)
|
23
|
+
@cc.set_coordinate(5, 6)
|
24
|
+
@cc.set_coordinate(7, 8)
|
25
|
+
end
|
26
|
+
it {@cc.coordinates.size.should == 3}
|
27
|
+
it {@cc.coordinates.should == [[1,2],[3,4],[5,6]]}
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#valid_coordinates?" do
|
33
|
+
|
34
|
+
context "coordinates size not enough" do
|
35
|
+
before do
|
36
|
+
@cc = GeoTriangleExt::CircumCenter.new
|
37
|
+
@cc.set_coordinate(1, 2)
|
38
|
+
@cc.set_coordinate(3, 4)
|
39
|
+
end
|
40
|
+
it {@cc.coordinates.size.should == 2}
|
41
|
+
it {@cc.valid_coordinates?.should be_false}
|
42
|
+
end
|
43
|
+
|
44
|
+
context "invalid coordinate format" do
|
45
|
+
before do
|
46
|
+
@cc = GeoTriangleExt::CircumCenter.new
|
47
|
+
@cc.set_coordinate(1, 2)
|
48
|
+
@cc.set_coordinate(3, 4)
|
49
|
+
@cc.coordinates << 5
|
50
|
+
end
|
51
|
+
it {@cc.coordinates.size.should == 3}
|
52
|
+
it {@cc.valid_coordinates?.should be_false}
|
53
|
+
end
|
54
|
+
|
55
|
+
context "valid coordinates" do
|
56
|
+
before do
|
57
|
+
@cc = GeoTriangleExt::CircumCenter.new
|
58
|
+
@cc.set_coordinate(1, 2)
|
59
|
+
@cc.set_coordinate(3, 4)
|
60
|
+
@cc.set_coordinate(5, 6)
|
61
|
+
@cc.set_coordinate(7, 8)
|
62
|
+
end
|
63
|
+
it {@cc.coordinates.size.should == 3}
|
64
|
+
it {@cc.valid_coordinates?.should be_true}
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
describe ".create" do
|
70
|
+
|
71
|
+
context "create object" do
|
72
|
+
subject {GeoTriangleExt::CircumCenter.create([1,2], [3,4], [5,6])}
|
73
|
+
it {should be_instance_of(GeoTriangleExt::CircumCenter)}
|
74
|
+
its(:coordinates) {should == [[1,2],[3,4],[5,6]]}
|
75
|
+
end
|
76
|
+
|
77
|
+
context "take 3 coordinates if given over 3" do
|
78
|
+
subject {GeoTriangleExt::CircumCenter.create([1,2], [3,4], [5,6],[7,8])}
|
79
|
+
it {should be_instance_of(GeoTriangleExt::CircumCenter)}
|
80
|
+
its(:coordinates) {should == [[1,2],[3,4],[5,6]]}
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "#functions" do
|
86
|
+
|
87
|
+
context "3 functions from triangle coordinates" do
|
88
|
+
before do
|
89
|
+
@cc = GeoTriangleExt::CircumCenter.create([0,4],[2,0],[5,6])
|
90
|
+
end
|
91
|
+
it {@cc.functions.size.should == 3}
|
92
|
+
end
|
93
|
+
|
94
|
+
context "not created if not valid coordinates" do
|
95
|
+
before do
|
96
|
+
@cc = GeoTriangleExt::CircumCenter.new
|
97
|
+
@cc.set_coordinate(1, 2)
|
98
|
+
@cc.set_coordinate(3, 4)
|
99
|
+
end
|
100
|
+
it {@cc.functions.should be_empty}
|
101
|
+
end
|
102
|
+
|
103
|
+
context "2 functions if 2 coordinates x or y is same" do
|
104
|
+
before do
|
105
|
+
@cc = GeoTriangleExt::CircumCenter.create([0,4],[2,0],[5,4])
|
106
|
+
end
|
107
|
+
it {@cc.functions.size.should == 2}
|
108
|
+
end
|
109
|
+
|
110
|
+
context "1 functions if right triangle" do
|
111
|
+
before do
|
112
|
+
@cc = GeoTriangleExt::CircumCenter.create([0,4],[2,0],[0,0])
|
113
|
+
end
|
114
|
+
it {@cc.functions.size.should == 1}
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "#valid_functions?" do
|
120
|
+
|
121
|
+
context "valid triangle coordinates" do
|
122
|
+
before do
|
123
|
+
@cc = GeoTriangleExt::CircumCenter.create([0,4],[2,0],[5,6])
|
124
|
+
end
|
125
|
+
it {@cc.functions.size.should == 3}
|
126
|
+
it {@cc.valid_functions?.should be_true}
|
127
|
+
end
|
128
|
+
|
129
|
+
context "2 functions is valid" do
|
130
|
+
before do
|
131
|
+
@cc = GeoTriangleExt::CircumCenter.create([0,4],[2,0],[5,4])
|
132
|
+
end
|
133
|
+
it {@cc.functions.size.should == 2}
|
134
|
+
it {@cc.valid_functions?.should be_true}
|
135
|
+
end
|
136
|
+
|
137
|
+
context "1 functions is not valid" do
|
138
|
+
before do
|
139
|
+
@cc = GeoTriangleExt::CircumCenter.create([0,4],[2,0],[0,0])
|
140
|
+
end
|
141
|
+
it {@cc.functions.size.should == 1}
|
142
|
+
it {@cc.valid_functions?.should be_false}
|
143
|
+
end
|
144
|
+
|
145
|
+
context "3 coordinates on same line" do
|
146
|
+
before do
|
147
|
+
@cc = GeoTriangleExt::CircumCenter.create([0,4],[2,0],[4,-4])
|
148
|
+
end
|
149
|
+
it {@cc.functions.size.should == 3}
|
150
|
+
it {@cc.valid_functions?.should be_false}
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
describe "#center" do
|
156
|
+
|
157
|
+
context "triangle coordinates" do
|
158
|
+
before do
|
159
|
+
cc = GeoTriangleExt::CircumCenter.create([0,4],[2,0],[5,6])
|
160
|
+
@x, @y = cc.center
|
161
|
+
end
|
162
|
+
it {@x.round(5).to_f.should == 3.25}
|
163
|
+
it {@y.round(5).to_f.should == 3.125}
|
164
|
+
end
|
165
|
+
|
166
|
+
context "2 coordinates x or y is same" do
|
167
|
+
before do
|
168
|
+
cc = GeoTriangleExt::CircumCenter.create([0,4],[2,0],[5,4])
|
169
|
+
@x, @y = cc.center
|
170
|
+
end
|
171
|
+
it {@x.round(5).to_f.should == 2.5}
|
172
|
+
it {@y.round(5).to_f.should == 2.75}
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
178
|
+
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
describe GeoTriangleExt::LinearFunction do
|
3
|
+
|
4
|
+
describe "#valid?" do
|
5
|
+
|
6
|
+
context "ax == bx" do
|
7
|
+
before do
|
8
|
+
@lf = GeoTriangleExt::LinearFunction.new
|
9
|
+
@lf.ax = 1
|
10
|
+
@lf.ay = 2
|
11
|
+
@lf.bx = 1
|
12
|
+
@lf.by = 5
|
13
|
+
end
|
14
|
+
it {@lf.valid?.should be_false}
|
15
|
+
end
|
16
|
+
|
17
|
+
context "bx == by" do
|
18
|
+
before do
|
19
|
+
@lf = GeoTriangleExt::LinearFunction.new
|
20
|
+
@lf.ax = 1
|
21
|
+
@lf.ay = 2
|
22
|
+
@lf.bx = 7
|
23
|
+
@lf.by = 2
|
24
|
+
end
|
25
|
+
it {@lf.valid?.should be_false}
|
26
|
+
end
|
27
|
+
|
28
|
+
context "unrelated" do
|
29
|
+
before do
|
30
|
+
@lf = GeoTriangleExt::LinearFunction.new
|
31
|
+
@lf.ax = 1
|
32
|
+
@lf.ay = 2
|
33
|
+
@lf.bx = 7
|
34
|
+
@lf.by = 0
|
35
|
+
end
|
36
|
+
it {@lf.valid?.should be_true}
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
describe ".create" do
|
42
|
+
subject{GeoTriangleExt::LinearFunction.create(1, 2, 7, 0)}
|
43
|
+
it {should be_instance_of(GeoTriangleExt::LinearFunction)}
|
44
|
+
its(:ax) {should == 1.0}
|
45
|
+
its(:ay) {should == 2.0}
|
46
|
+
its(:bx) {should == 7.0}
|
47
|
+
its(:by) {should == 0.0}
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#middle_point" do
|
51
|
+
|
52
|
+
context "positive number only" do
|
53
|
+
before do
|
54
|
+
@lf = GeoTriangleExt::LinearFunction.create(1, 2, 7, 1)
|
55
|
+
end
|
56
|
+
it {@lf.middle_point.should == [4.0, 1.5]}
|
57
|
+
end
|
58
|
+
|
59
|
+
context "include negative number" do
|
60
|
+
before do
|
61
|
+
@lf = GeoTriangleExt::LinearFunction.create(1, 2, -7, -1)
|
62
|
+
end
|
63
|
+
it {@lf.middle_point.should == [-3.0, 0.5]}
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#slope" do
|
69
|
+
before do
|
70
|
+
@lf = GeoTriangleExt::LinearFunction.create(0, 4, 2, 0)
|
71
|
+
end
|
72
|
+
it {@lf.slope.should == -2.0}
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#intercept" do
|
76
|
+
before do
|
77
|
+
@lf = GeoTriangleExt::LinearFunction.create(0, 4, 2, 0)
|
78
|
+
end
|
79
|
+
it {@lf.intercept.should == 4.0}
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "#orthogonal_slope" do
|
83
|
+
before do
|
84
|
+
@lf = GeoTriangleExt::LinearFunction.create(0, 4, 2, 0)
|
85
|
+
end
|
86
|
+
it {@lf.orthogonal_slope.should == 0.5}
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "#orthogonal_intercept" do
|
90
|
+
before do
|
91
|
+
@lf = GeoTriangleExt::LinearFunction.create(0, 4, 2, 0)
|
92
|
+
end
|
93
|
+
it {@lf.orthogonal_intercept.should == 1.5}
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
describe GravityCenter do
|
3
|
+
|
4
|
+
describe ".create" do
|
5
|
+
|
6
|
+
context "3 coordinates set" do
|
7
|
+
subject {GravityCenter.create([1,2],[3,4],[5,6])}
|
8
|
+
it {should be_instance_of(GravityCenter)}
|
9
|
+
its(:x1) {should == 1.0}
|
10
|
+
its(:y1) {should == 2.0}
|
11
|
+
its(:x2) {should == 3.0}
|
12
|
+
its(:y2) {should == 4.0}
|
13
|
+
its(:x3) {should == 5.0}
|
14
|
+
its(:y3) {should == 6.0}
|
15
|
+
end
|
16
|
+
|
17
|
+
context "6 numbers set" do
|
18
|
+
subject {GravityCenter.create(10,20,30,40,50,60)}
|
19
|
+
it {should be_instance_of(GravityCenter)}
|
20
|
+
its(:x1) {should == 10.0}
|
21
|
+
its(:y1) {should == 20.0}
|
22
|
+
its(:x2) {should == 30.0}
|
23
|
+
its(:y2) {should == 40.0}
|
24
|
+
its(:x3) {should == 50.0}
|
25
|
+
its(:y3) {should == 60.0}
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#sx1, #sx2, #sy1, #sy2 is shifted coordinates for (x3,y3) to (0,0)" do
|
31
|
+
subject {GravityCenter.create([0,4],[2,0],[5,6])}
|
32
|
+
its(:sx1) {should == -5.0}
|
33
|
+
its(:sy1) {should == -2.0}
|
34
|
+
its(:sx2) {should == -3.0}
|
35
|
+
its(:sy2) {should == -6.0}
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#center_sx, #center_sy is gravity center of shifted triangle" do
|
39
|
+
subject {GravityCenter.create([0,4],[2,0],[5,6])}
|
40
|
+
it {subject.center_sx.round(6).to_f.should == -2.666667}
|
41
|
+
it {subject.center_sy.round(6).to_f.should == -2.666667}
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#center_x, #center_y is gravity center of original triangle" do
|
45
|
+
subject {GravityCenter.create([0,4],[2,0],[5,6])}
|
46
|
+
it {subject.center_x.round(6).to_f.should == 2.333333}
|
47
|
+
it {subject.center_y.round(6).to_f.should == 3.333333}
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#center is gravity center coordinate of triangle" do
|
51
|
+
before do
|
52
|
+
gc = GravityCenter.create([0,4],[2,0],[5,6])
|
53
|
+
@x, @y = gc.center
|
54
|
+
end
|
55
|
+
it {@x.round(6).to_f.should == 2.333333}
|
56
|
+
it {@y.round(6).to_f.should == 3.333333}
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'geo-triangle'
|
5
|
+
|
6
|
+
# Requires supporting files with custom matchers and macros, etc,
|
7
|
+
# in ./support/ and its subdirectories.
|
8
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: geo-triangle
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- parrot-studio
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-05-19 00:00:00 +09:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: rspec
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ~>
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.3.0
|
24
|
+
type: :development
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ~>
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 1.0.0
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: jeweler
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.6.0
|
46
|
+
type: :development
|
47
|
+
prerelease: false
|
48
|
+
version_requirements: *id003
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: rcov
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
type: :development
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: *id004
|
60
|
+
description: calculate center of 3 geo-coordinates(lat, lon)
|
61
|
+
email: parrot@users.sourceforge.jp
|
62
|
+
executables: []
|
63
|
+
|
64
|
+
extensions: []
|
65
|
+
|
66
|
+
extra_rdoc_files:
|
67
|
+
- LICENSE.txt
|
68
|
+
- README.rdoc
|
69
|
+
files:
|
70
|
+
- .document
|
71
|
+
- .rspec
|
72
|
+
- Gemfile
|
73
|
+
- Gemfile.lock
|
74
|
+
- LICENSE.txt
|
75
|
+
- README.rdoc
|
76
|
+
- Rakefile
|
77
|
+
- VERSION
|
78
|
+
- lib/geo-triangle.rb
|
79
|
+
- lib/geo_triangle_ext/circum_center.rb
|
80
|
+
- lib/geo_triangle_ext/linear_function.rb
|
81
|
+
- lib/gravity_center.rb
|
82
|
+
- spec/geo-triangle_spec.rb
|
83
|
+
- spec/geo_triangle_ext/circum_center_spec.rb
|
84
|
+
- spec/geo_triangle_ext/linear_function_spec.rb
|
85
|
+
- spec/gravity_center_spec.rb
|
86
|
+
- spec/spec_helper.rb
|
87
|
+
has_rdoc: true
|
88
|
+
homepage: http://github.com/parrot-studio/geo-triangle
|
89
|
+
licenses:
|
90
|
+
- MIT
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options: []
|
93
|
+
|
94
|
+
require_paths:
|
95
|
+
- lib
|
96
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
hash: 449437378648933997
|
102
|
+
segments:
|
103
|
+
- 0
|
104
|
+
version: "0"
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
+
none: false
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: "0"
|
111
|
+
requirements: []
|
112
|
+
|
113
|
+
rubyforge_project:
|
114
|
+
rubygems_version: 1.6.2
|
115
|
+
signing_key:
|
116
|
+
specification_version: 3
|
117
|
+
summary: calculate geo-triangle's gravity center
|
118
|
+
test_files: []
|
119
|
+
|