geo-triangle 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|