cf_sim 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9378e236733ed66fb70343fa5e33c508cfdba69f
4
+ data.tar.gz: 603031535dbc93e9dacc2ec9fce5f6415f9e6ba4
5
+ SHA512:
6
+ metadata.gz: 4a7aca9a5cf5bae58b1e715c8276f9faee4418718f00fd7230a34a877ef59631e911dffc1e03af3bf34796aedc36955b68ffc85a890640ab4f2458a738904683
7
+ data.tar.gz: aca9a38f0f726005d54b7a40cb3901dabb27551cf6521af330523a5f44233b2339633b1a1a2114b2b6b2425ea8d34f23275b0f8d20a86676534c7b4e6eecfcc9
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0
4
+ - 2.1
5
+ - 2.2
@@ -0,0 +1,13 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
6
+
7
+ Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
+
9
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
+
11
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
+
13
+ This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cf_sim.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 pinzolo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # CF Simulator
2
+ [![Build Status](https://travis-ci.org/pinzolo/cf_sim.svg)](http://travis-ci.org/pinzolo/cf_sim)
3
+ [![Coverage Status](https://coveralls.io/repos/pinzolo/cf_sim/badge.png)](https://coveralls.io/r/pinzolo/cf_sim)
4
+
5
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/cf_sim`. To experiment with that code, run `bin/console` for an interactive prompt.
6
+
7
+ TODO: Delete this and the text above, and describe your gem
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'cf_sim'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install cf_sim
24
+
25
+ ## Usage
26
+
27
+ TODO: Write usage instructions here
28
+
29
+ ## Development
30
+
31
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment. Run `bundle exec cf_sim` to use the code located in this directory, ignoring other installed copies of this gem.
32
+
33
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
34
+
35
+ ## Contributing
36
+
37
+ 1. Fork it ( https://github.com/pinzolo/cf_sim/fork )
38
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
39
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
40
+ 4. Push to the branch (`git push origin my-new-feature`)
41
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'test'
6
+ t.test_files = FileList['test/cf_sim/*_test.rb']
7
+ t.verbose = true
8
+ end
9
+ task default: :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "cf_sim"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
data/cf_sim.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'cf_sim/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "cf_sim"
8
+ spec.version = CfSim::VERSION
9
+ spec.authors = ["pinzolo"]
10
+ spec.email = ["pinzolo@gmail.com"]
11
+ spec.summary = %q{Multi layered CF simulator}
12
+ spec.description = %q{Propose multi layered control fields pattern by given portals.}
13
+ spec.homepage = "https://github.com/pinzolo/cf_sim"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler"#, "~> 1.8"
22
+ spec.add_development_dependency "rake"#, "~> 10.0"
23
+ spec.add_development_dependency 'test-unit'
24
+ spec.add_development_dependency 'coveralls'
25
+
26
+ spec.add_dependency 'thor'
27
+ end
data/exe/cf_sim ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "cf_sim"
4
+ CfSim::CLI.start
data/lib/cblxy.rb ADDED
@@ -0,0 +1,262 @@
1
+ # see https://github.com/KMR-zoar/cblxy
2
+ include Math
3
+
4
+
5
+ #定数の定義
6
+ #ベッセル楕円体
7
+ $aB = 6377397.155 #長半径
8
+ $FB = 299.152813 #逆扁平率
9
+ #GRS80楕円体
10
+ $aG = 6378137.0 #長半径
11
+ $FG = 298.257222101 #逆扁平率
12
+ #共通定数
13
+ $sbyS = 0.9999 #原点における縮尺係数
14
+ $a = 0.0 #長半径
15
+ $F = 0.0 #逆扁平率
16
+ $e = 0.0 #第一離心率
17
+ $phi0 = 0.0 #原点緯度
18
+ $lambda0 = 0.0 #原点経度
19
+ $bits = ARGV[2] #出力値(0 = 緯度 or X, 1 = 経度 or Y)
20
+
21
+ #世界測地系で緯度経度を平面直角座標に変換するメソッド
22
+ def blxy(phi1, lamda1,k)
23
+ $a = $aG #GRS80楕円体の定数を代入
24
+ $F = $FG
25
+ genten(k)
26
+
27
+ bl2xy(phi1, lamda1)
28
+
29
+ end
30
+
31
+ #世界測地系で平面直角座標を緯度経度に変換するメソッド
32
+ def xybl(phi1,lamda1,k)
33
+ $a = $aG #GRS80楕円体の定数を代入
34
+ $F = $FG
35
+ genten(k)
36
+
37
+ xy2bl(phi1, lamda1)
38
+ end
39
+
40
+ #緯度経度を平面直角座標に変換する計算
41
+ def bl2xy(phi, lamda)
42
+ $e = sqrt(2.0 * $F - 1.0) / $F
43
+
44
+ phi1 = deg2rad(phi)
45
+ lamda1 = deg2rad(lamda)
46
+
47
+ s0 = kocyou($phi0)
48
+ s1 = kocyou(phi1)
49
+
50
+ ut = $a / sqrt(1.0 - $e ** 2.0 * sin(phi1) ** 2.0)
51
+ conp = cos(phi1)
52
+ t1 = tan(phi1)
53
+ dlamda = lamda1 - $lamda0
54
+ eta2 = ($e ** 2.0 / (1.0 - $e ** 2.0)) * conp ** 2.0
55
+
56
+ #X座標値の算出
57
+ v1 = 5.0 - t1 ** 2.0 + 9.0 * eta2 + 4.0 * eta2 ** 2.0
58
+ v2 = -61.0 + 58.0 * t1 ** 2.0 - t1 ** 4.0 - 270.0 * eta2 + 330.0 * t1 ** 2.0 * eta2
59
+ v3 = -1385.0 + 3111.0 * t1 ** 2.0 - 543.0 * t1 ** 4.0 + t1 ** 6.0
60
+
61
+ x = ((s1 - s0) + ut * conp ** 2.0 * t1 * dlamda ** 2.0 / 2.0 + ut * conp ** 4.0 * t1 * v1 * dlamda ** 4.0 / 24.0 - ut * conp ** 6.0 * t1 * v2 * dlamda ** 6.0 / 720.0 - ut * conp ** 8.0 * t1 * v3 * dlamda ** 8.0 / 40320.0) * $sbyS
62
+
63
+ #Y座標値の算出
64
+ v1 = -1.0 + t1 ** 2.0 - eta2
65
+ v2 = -5.0 + 18.0 * t1 ** 2.0 - t1 ** 4.0 - 14.0 * eta2 + 58.0 * t1 ** 2.0 * eta2
66
+ v3 = -61.0 + 479.0 * t1 ** 2.0 - 179.0 * t1 ** 4.0 + t1 ** 6.0
67
+
68
+ y = (ut * conp * dlamda - ut * conp ** 3.0 * v1 * dlamda ** 3.0 / 6.0 - ut * conp ** 5.0 * v2 * dlamda ** 5.0 / 120.0 - ut * conp ** 7.0 * v3 * dlamda ** 7.0 / 5040.0) * $sbyS
69
+
70
+ return [x,y]
71
+
72
+ end
73
+
74
+ #平面直角座標から緯度経度に変換する計算
75
+ def xy2bl(x,y)
76
+ $e = sqrt(2.0 * $F - 1.0) / $F
77
+
78
+ phi1 = suisen(x)
79
+
80
+ ut = $a / sqrt( 1.0 - $e ** 2.0 * sin(phi1) ** 2.0)
81
+ conp = cos(phi1)
82
+ t1 = tan(phi1)
83
+ eta2 = ($e ** 2.0 / (1.0 - $e ** 2.0)) * conp ** 2.0
84
+
85
+ #緯度算出
86
+ yy = y / $sbyS
87
+ v1 = 1.0 + eta2
88
+ v2 = 5.0 + 3.0 * t1 ** 2.0 + 6.0 * eta2 - 6.0 * t1 ** 2.0 * eta2 - 3.0 * eta2 ** 2.0 - 9.0 * t1 ** 2.0 * eta2 ** 2.0
89
+ v3 = 61.0 + 90.0 * t1 ** 2.0 + 45.0 * t1 ** 4.0 + 107.0 * eta2 - 162.0 * t1 ** 2.0 * eta2 - 45.0 * t1 ** 4.0 * eta2
90
+ v4 = 1385.0 + 3633.0 * t1 ** 2.0 + 4095.0 * t1 ** 4.0 + 1575.0 * t1 ** 6.0
91
+
92
+ phir = -(v1 / (2.0 * ut ** 2.0)) * yy ** 2.0
93
+ phir = phir + (v2 / (24.0 * ut ** 4.0)) * yy ** 4.0
94
+ phir = phir - (v3 / (720.0 * ut ** 6.0)) * yy ** 6.0
95
+ phir = phir + (v4 / (40320.0 * ut ** 8.0)) * yy ** 8.0
96
+ phir = phir * t1
97
+ phir = phir + phi1
98
+ phir = rad2deg(phir)
99
+
100
+ #経度算出
101
+ v1 = ut * conp
102
+ v2 = 1.0 + 2.0 * t1 ** 2.0 + eta2
103
+ v3 = 5.0 + 28.0 * t1 ** 2.0 + 24.0 * t1 ** 4.0 + 6.0 * eta2 + 8.0 * t1 ** 2.0 * eta2
104
+ v4 = 61.0 + 662.0 * t1 ** 2.0 + 1320.0 * t1 ** 4.0 + 720.0 * t1 ** 6.0
105
+
106
+ lamdar = (1.0 / v1) * yy
107
+ lamdar = lamdar - (v2 / (6.0 * ut ** 2.0 * v1)) * yy ** 3.0
108
+ lamdar = lamdar + (v3 / (120.0 * ut ** 4.0 * v1)) * yy ** 5.0
109
+ lamdar = lamdar - (v4 / (5040.0 * ut ** 6.0 * v1)) * yy ** 7.0
110
+ lamdar = lamdar + $lamda0
111
+
112
+ lamdar = rad2deg(lamdar)
113
+
114
+ return [phir,lamdar]
115
+ end
116
+
117
+ #座標系原点の緯度経度
118
+ def genten(k)
119
+
120
+ err = "座標系が正しく指定されていません"
121
+
122
+ case k
123
+ when 1
124
+ degen = [330000.0,1293000.0]
125
+ when 2
126
+ degen = [330000.0,1310000.0]
127
+ when 3
128
+ degen = [360000.0,1321000.0]
129
+ when 4
130
+ degen = [330000.0,1333000.0]
131
+ when 5
132
+ degen = [360000.0,1342000.0]
133
+ when 6
134
+ degen = [360000.0,1360000.0]
135
+ when 7
136
+ degen = [360000.0,1371000.0]
137
+ when 8
138
+ degen = [360000.0,1383000.0]
139
+ when 9
140
+ degen = [360000.0,1395000.0]
141
+ when 10
142
+ degen = [400000.0,1405000.0]
143
+ when 11
144
+ degen = [440000.0,1401500.0]
145
+ when 12
146
+ degen = [440000.0,1421500.0]
147
+ when 13
148
+ degen = [440000.0,1441500.0]
149
+ when 14
150
+ degen = [260000.0,1420000.0]
151
+ when 15
152
+ degen = [260000.0,1273000.0]
153
+ when 16
154
+ degen = [260000.0,1240000.0]
155
+ when 17
156
+ degen = [260000.0,1310000.0]
157
+ when 18
158
+ degen = [200000.0,1360000.0]
159
+ when 19
160
+ degen = [260000.0,1540000.0]
161
+ else
162
+ degen = err
163
+ end
164
+
165
+ unless degen == err
166
+ $phi0 = (deg2rad degen[0])
167
+ $lamda0 = (deg2rad degen[1])
168
+ return [$phi0,$lamda0]
169
+ else
170
+ return err
171
+ end
172
+ end
173
+
174
+
175
+
176
+ #度分秒からラジアンへの変換
177
+ def deg2rad(deg)
178
+ radbase = PI / 180.0
179
+ if deg < 0
180
+ fugou = -1.0
181
+ else
182
+ fugou = 1.0
183
+ end
184
+
185
+ deg = deg.abs
186
+
187
+ angle = (deg / 10000.0).to_i
188
+ minute = ((deg / 100.0).to_i - (angle * 100.0)).to_f
189
+ second = deg - (angle * 10000.0) - (minute * 100.0)
190
+ rad = fugou * (angle + (minute + (second / 60.0)) / 60.0)
191
+ rad = rad * radbase
192
+
193
+ end
194
+
195
+ #ラジアンから度分秒への変換
196
+ def rad2deg(rad)
197
+
198
+ degbase = 180.0 / PI
199
+
200
+ if rad < 0
201
+ fugou = -1.0
202
+ else
203
+ fugou = 1.0
204
+ end
205
+
206
+ rad = rad.abs
207
+
208
+ rad = rad * degbase
209
+ angle = rad.to_i
210
+ rad = (rad - angle).to_f * 60.0
211
+ minute = rad.to_i
212
+ second = (rad - minute).to_f * 60.0
213
+
214
+ deg = fugou * (angle * 10000.0 + minute * 100.0 + second)
215
+ end
216
+
217
+ #緯度から赤道への子午線弧長を計算する
218
+ def kocyou(ido)
219
+ e2 = $e ** 2.0
220
+ e4 = $e ** 4.0
221
+ e6 = $e ** 6.0
222
+ e8 = $e ** 8.0
223
+ e10 = $e ** 10.0
224
+ e12 = $e ** 12.0
225
+ e14 = $e ** 14.0
226
+ e16 = $e ** 16.0
227
+
228
+ a = 1.0 + 3.0 / 4.0 * e2 + 45.0 / 64.0 * e4 + 175.0 / 256.0 * e6 + 11025.0 / 16384.0 * e8 + 43659.0 / 65536.0 * e10 + 693693.0 / 1048576.0 * e12 + 19324305.0 / 29360128.0 * e14 + 4927697775.0 / 7516192768.0 * e16
229
+ b = 3.0 / 4.0 * e2 + 15.0 / 16.0 * e4 + 525.0 / 512.0 * e6 + 2205.0 / 2048.0 * e8 + 72765.0 / 65536.0 * e10 + 297297.0 / 262144.0 * e12 + 135270135.0 / 117440512.0 * e14 + 547521975.0 / 469762048.0 * e16
230
+ c = 15.0 / 64.0 * e4 + 105.0 / 256.0 * e6 + 2205.0 / 4096.0 * e8 + 10395.0 / 16384.0 * e10 + 1486485.0 / 2097152.0 * e12 + 45090045.0 / 58720256.0 * e14 + 766530765.0 / 939524096.0 * e16
231
+ d = 35.0 / 512.0 * e6 + 315.0 / 2048.0 * e8 + 31185.0 / 131072.0 * e10 + 165165.0 / 524288.0 * e12 + 45090045.0 / 117440512.0 * e14 + 209053845.0 / 469762048.0 * e16
232
+ e = 315.0 / 16384.0 * e8 + 3465.0 / 65536.0 * e10 + 99099.0 / 1048576.0 * e12 + 4099095.0 / 29360128.0 * e14 + 348423075.0 / 1879048192.0 * e16
233
+ f = 693.0 / 131072 * e10 + 9009.0 / 524288.0 * e12 + 4099095.0 / 117440512.0 * e14 + 26801775.0 / 469762048.0 * e16
234
+ g = 3003 / 2097152.0 * e12 + 315315.0 / 58720256.0 * e14 + 11486475.0 / 939524096.0 * e16
235
+ h = 45045.0 / 117440512.0 * e14 + 765765.0 / 469762048.0 * e16
236
+ i = 765765.0 / 7516192768.0 * e16
237
+
238
+ sigosen = $a * (1.0 - e2) * (a * ido - b * sin(ido * 2.0) / 2.0 + c * sin(ido * 4.0) / 4.0 - d * sin(ido * 6.0) / 6.0 + e * sin(ido * 8.0) / 8.0 - f * sin(ido * 10.0) / 10.0 + g * sin(ido * 12.0) / 12.0 - h * sin(ido * 14.0) / 14.0 + i * sin(ido * 16.0) / 16.0)
239
+ end
240
+
241
+ def suisen(x)
242
+ s0 = kocyou($phi0)
243
+ m = s0 + x / $sbyS
244
+ cnt = 0
245
+ phin = $phi0
246
+ e2 = $e ** 2.0
247
+ phi0 = phin
248
+
249
+ while
250
+ cnt = cnt + 1
251
+ phi0 = phin
252
+ sn = kocyou(phin)
253
+ v1 = 2.0 * (sn - m) * ((1.0 - e2 * sin(phin) ** 2.0) ** 1.5)
254
+ v2 = 3.0 * e2 * (sn - m) * sin(phin) * cos(phin) * sqrt(1.0 - e2 * sin(phin) ** 2.0) - 2.0 * $a * (1.0 - e2)
255
+ phin = phin +v1 / v2
256
+ if ((phin - phi0).abs < 0.00000000000001) or cnt > 100
257
+ break
258
+ end
259
+ end
260
+ return phin
261
+
262
+ end
data/lib/cf_sim/cli.rb ADDED
@@ -0,0 +1,31 @@
1
+ require 'thor'
2
+
3
+ class CfSim::CLI < Thor
4
+ desc 'max_area DATA_FILE', 'print max area control fields URL.'
5
+ def max_area(data_file)
6
+ finder = load_finder_from(data_file)
7
+ fields = finder.find_max_area_fields
8
+ puts @generator.fields_link(fields)
9
+ end
10
+
11
+ desc 'max_count DATA_FILE', 'print max count control fields URL list.'
12
+ def max_count(data_file)
13
+ finder = load_finder_from(data_file)
14
+ fields_list = finder.find_max_count_fields_list
15
+ max_area = fields_list.first.total_area
16
+ fields_list.each do |fields|
17
+ area_rate = (fields.total_area * 100 / max_area).round(3)
18
+ puts "#{@generator.fields_link(fields)} (Area rate: #{area_rate})"
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def load_finder_from(data_file)
25
+ portals = CfSim::DataFileParser.new(data_file).parse
26
+ portal_map = CfSim::PortalMap.new(portals)
27
+ @generator = CfSim::IntelMapUrlGenerator.new(portal_map)
28
+ CfSim::ControlFieldSetFinder.new(CfSim::PointList.new(portal_map.points).creatable_fields)
29
+ end
30
+ end
31
+
@@ -0,0 +1,19 @@
1
+ require 'cf_sim/control_field_set'
2
+
3
+ class CfSim::CoexistableFieldMap
4
+ include Enumerable
5
+
6
+ def initialize(fields)
7
+ @map = fields.each_with_object({}) do |field, map|
8
+ map[field] = CfSim::ControlFieldSet.new(fields.reject { |other| field == other || field.intersected?(other) })
9
+ end
10
+ end
11
+
12
+ def [](field)
13
+ @map[field]
14
+ end
15
+
16
+ def each
17
+ @map.each { |field, coexistable_fields| yield field, coexistable_fields }
18
+ end
19
+ end
@@ -0,0 +1,55 @@
1
+ require 'cf_sim/link'
2
+
3
+ class CfSim::ControlField
4
+ attr_reader :point1, :point2, :point3, :link1, :link2, :link3
5
+
6
+ def initialize(point1, point2, point3)
7
+ @point1, @point2, @point3 = point1, point2, point3
8
+ @link1 = CfSim::Link.new(point1, point2)
9
+ @link2 = CfSim::Link.new(point2, point3)
10
+ @link3 = CfSim::Link.new(point3, point1)
11
+ end
12
+
13
+ def ==(other)
14
+ eql?(other)
15
+ end
16
+
17
+ def eql?(other)
18
+ (points - other.points).empty?
19
+ end
20
+
21
+ def hash
22
+ point1.hash + point2.hash + point3.hash
23
+ end
24
+
25
+ def points
26
+ @points ||= [@point1, @point2, @point3].freeze
27
+ end
28
+
29
+ def links
30
+ @links ||= [@link1, @link2, @link3].freeze
31
+ end
32
+
33
+ def area
34
+ @area ||= calculate_area
35
+ end
36
+
37
+ def intersected?(other)
38
+ links.any? do |link1|
39
+ other.links.any? do |link2|
40
+ link1.intersected?(link2)
41
+ end
42
+ end
43
+ end
44
+
45
+ def to_s
46
+ "#{point1.name} -> #{point2.name} -> #{point3.name}"
47
+ end
48
+
49
+ private
50
+
51
+ def calculate_area
52
+ s = links.map(&:length).inject(:+) / 2.0
53
+ Math.sqrt(s * (s - link1.length) * (s - link2.length) * (s - link3.length))
54
+ end
55
+ end
@@ -0,0 +1,64 @@
1
+ require 'forwardable'
2
+
3
+ class CfSim::ControlFieldSet
4
+ extend Forwardable
5
+ include Enumerable
6
+
7
+ attr_reader :control_fields
8
+ def_delegators :@control_fields, :clear, :each, :empty?, :hash, :size
9
+
10
+ def initialize(*fields)
11
+ @control_fields = fields.flatten.dup
12
+ end
13
+
14
+ def total_area
15
+ @total_area ||= @control_fields.inject(0) { |area, field| area += field.area }
16
+ end
17
+
18
+ def -(fields)
19
+ CfSim::ControlFieldSet.new(@control_fields - extract_field_array(fields))
20
+ end
21
+
22
+ def &(fields)
23
+ CfSim::ControlFieldSet.new(@control_fields & extract_field_array(fields))
24
+ end
25
+
26
+ def +(fields)
27
+ CfSim::ControlFieldSet.new(@control_fields + extract_field_array(fields))
28
+ end
29
+
30
+ def ==(other)
31
+ eql?(other)
32
+ end
33
+
34
+ def eql?(other)
35
+ other.class == CfSim::ControlFieldSet &&
36
+ @control_fields.size == other.control_fields.size &&
37
+ (@control_fields - other.control_fields).empty?
38
+ end
39
+
40
+ def dup
41
+ # initialize 内で dup しているためここでする必要はない
42
+ CfSim::ControlFieldSet.new(@control_fields)
43
+ end
44
+
45
+ def to_s
46
+ text = "Fields:\n"
47
+ @control_fields.each { |field| text << " #{field}\n" }
48
+ text << "Total area: #{total_area}"
49
+ text
50
+ end
51
+
52
+ private
53
+
54
+ def extract_field_array(fields)
55
+ if fields.is_a?(Array)
56
+ fields
57
+ elsif fields.is_a?(CfSim::ControlFieldSet)
58
+ fields.control_fields
59
+ else
60
+ raise 'Only for Array or ControlFieldSet'
61
+ end
62
+ end
63
+ end
64
+
@@ -0,0 +1,83 @@
1
+ require 'cf_sim/coexistable_field_map'
2
+ require 'cf_sim/control_field_set'
3
+
4
+ class CfSim::ControlFieldSetFinder
5
+ def initialize(fields, limit_field_count = 1)
6
+ @fields = CfSim::ControlFieldSet.new(fields.sort_by(&:area).reverse)
7
+ @coexistable_field_map = CfSim::CoexistableFieldMap.new(@fields)
8
+ @limit_field_count = limit_field_count
9
+ end
10
+
11
+ def find_max_area_fields
12
+ @max_area_control_fields = nil
13
+ find_recursively(CfSim::ControlFieldSet.new, @fields, :max_area)
14
+ @max_area_control_fields
15
+ end
16
+
17
+ def find_all_fields_list
18
+ @control_fields_list = []
19
+ find_recursively(CfSim::ControlFieldSet.new, @fields, :all)
20
+ @control_fields_list
21
+ end
22
+
23
+ def find_max_count_fields_list
24
+ @max_count_control_fields_list = []
25
+ find_recursively(CfSim::ControlFieldSet.new, @fields, :max_count)
26
+ @max_count_control_fields_list.sort_by(&:total_area).reverse
27
+ end
28
+
29
+ private
30
+
31
+ def find_recursively(fields, coexistable_fields, type)
32
+ return if ignore?(fields, coexistable_fields, type)
33
+
34
+ if coexistable_fields.empty?
35
+ deploy(fields, type)
36
+ else
37
+ coexistable_fields.each do |field|
38
+ find_recursively(fields + [field], coexistable_fields & (@coexistable_field_map[field].reject { |f| f.area > field.area }) , type)
39
+ end
40
+ end
41
+ end
42
+
43
+ def deploy(fields, type)
44
+ case type
45
+ when :max_area
46
+ replace_if_max(fields)
47
+ when :all
48
+ append_to_list(fields, @control_fields_list)
49
+ when :max_count
50
+ append_or_create_if_max_count(fields)
51
+ end
52
+ end
53
+
54
+ def replace_if_max(fields)
55
+ @max_area_control_fields = fields if @max_area_control_fields.nil? || fields.total_area > @max_area_control_fields.total_area
56
+ end
57
+
58
+ def append_to_list(fields, fields_list)
59
+ fields_list << fields unless fields_list.include?(fields)
60
+ end
61
+
62
+ def append_or_create_if_max_count(fields)
63
+ if @max_count_control_fields_list.empty? || @max_count_control_fields_list.first.size == fields.size
64
+ append_to_list(fields, @max_count_control_fields_list)
65
+ elsif @max_count_control_fields_list.first.size < fields.size
66
+ @max_count_control_fields_list = [fields]
67
+ end
68
+ end
69
+
70
+ def ignore?(fields, coexistable_fields, type)
71
+ field_count = fields.size + coexistable_fields.size
72
+ case type
73
+ when :max_area
74
+ @max_area_control_fields && fields.total_area + coexistable_fields.total_area <= @max_area_control_fields.total_area
75
+ when :all
76
+ field_count < @limit_field_count
77
+ when :max_count
78
+ field_count < @limit_field_count && @max_count_control_fields_list.any? && field_count < @max_count_control_fields_list.first.size
79
+ else
80
+ false
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,43 @@
1
+ # 本来なら都道府県によって座標系が決定されるべきだが、とりあえず簡易的に最も近いものを対象とする
2
+ class CfSim::CordinationSystem
3
+ attr_reader :latitude, :longitude
4
+
5
+ ORIGIN_MAP = { 1 => [33.00000,129.30000],
6
+ 2 => [33.00000,131.00000],
7
+ 3 => [36.00000,132.10000],
8
+ 4 => [33.00000,133.30000],
9
+ 5 => [36.00000,134.20000],
10
+ 6 => [36.00000,136.00000],
11
+ 7 => [36.00000,137.10000],
12
+ 8 => [36.00000,138.30000],
13
+ 9 => [36.00000,139.50000],
14
+ 10 => [40.00000,140.50000],
15
+ 11 => [44.00000,140.15000],
16
+ 12 => [44.00000,142.15000],
17
+ 13 => [44.00000,144.15000],
18
+ 14 => [26.00000,142.00000],
19
+ 15 => [26.00000,127.30000],
20
+ 16 => [26.00000,124.00000],
21
+ 17 => [26.00000,131.00000],
22
+ 18 => [20.00000,136.00000],
23
+ 19 => [26.00000,154.00000] }
24
+
25
+ def initialize(latitude, longitude)
26
+ @latitude = latitude
27
+ @longitude = longitude
28
+ end
29
+
30
+ def nearest_system_number
31
+ @nearest_system_number ||= ORIGIN_MAP.min_by { |_, origin| distance(origin) }.first
32
+ end
33
+
34
+ def nearest_origin
35
+ @nearest_origin ||= ORIGIN_MAP[nearest_system_number]
36
+ end
37
+
38
+ private
39
+
40
+ def distance(origin)
41
+ Math.sqrt((origin.first - @latitude) ** 2 + (origin.last - @longitude) ** 2)
42
+ end
43
+ end
@@ -0,0 +1,23 @@
1
+ class CfSim::DataFileParser
2
+ def initialize(data_file_path)
3
+ @data_file_path = data_file_path
4
+ end
5
+
6
+ def parse
7
+ @portals = []
8
+ File.open(@data_file_path) do |file|
9
+ file.each_line do |line|
10
+ next if line.strip.empty?
11
+ @portals << create_portal_from_line(line)
12
+ end
13
+ end
14
+ @portals
15
+ end
16
+
17
+ private
18
+
19
+ def create_portal_from_line(line)
20
+ latitude, longitude, *rest = line.split(',')
21
+ CfSim::Portal.new(rest.join(',').strip, latitude.to_f, longitude.to_f)
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ class CfSim::IntelMapUrlGenerator
2
+ def initialize(portal_map)
3
+ @portal_map = portal_map
4
+ end
5
+
6
+ def portal_link(portal)
7
+ "https://www.ingress.com/intel?ll=#{portal.latitude},#{portal.longitude}&pll=#{portal.latitude},#{portal.longitude}"
8
+ end
9
+
10
+ def fields_link(fields)
11
+ links = fields.each_with_object([]) { |field, list| list << field.links }.flatten.uniq
12
+ base_point = @portal_map.find_portal(links.first.source_point)
13
+ url_base = "https://www.ingress.com/intel?ll=#{base_point.latitude},#{base_point.longitude}&pls="
14
+ link_url_params = links.map do |link|
15
+ source_portal = @portal_map.find_portal(link.source_point)
16
+ destination_portal = @portal_map.find_portal(link.destination_point)
17
+ "#{source_portal.latitude},#{source_portal.longitude},#{destination_portal.latitude},#{destination_portal.longitude}"
18
+ end
19
+ url_base + link_url_params.join('_')
20
+ end
21
+ end
@@ -0,0 +1,38 @@
1
+ class CfSim::Link
2
+ attr_reader :source_point, :destination_point
3
+
4
+ def initialize(source_point, destination_point)
5
+ raise 'Cannot link to same point' if source_point == destination_point
6
+ @source_point = source_point
7
+ @destination_point = destination_point
8
+ end
9
+
10
+ def length
11
+ @length ||= Math.sqrt((source_point.x - destination_point.x) ** 2 + (source_point.y - destination_point.y) ** 2)
12
+ end
13
+
14
+ def ==(other)
15
+ eql?(other)
16
+ end
17
+
18
+ def eql?(other)
19
+ (source_point == other.source_point && destination_point == other.destination_point) ||
20
+ (source_point == other.destination_point && destination_point == other.source_point)
21
+ end
22
+
23
+ def hash
24
+ source_point.hash + destination_point.hash
25
+ end
26
+
27
+ def intersected?(other)
28
+ ta = (other.source_point.x - other.destination_point.x) * (source_point.y - other.source_point.y) + (other.source_point.y - other.destination_point.y) * (other.source_point.x - source_point.x)
29
+ tb = (other.source_point.x - other.destination_point.x) * (destination_point.y - other.source_point.y) + (other.source_point.y - other.destination_point.y) * (other.source_point.x - destination_point.x)
30
+ tc = (source_point.x - destination_point.x) * (other.source_point.y - source_point.y) + (source_point.y - destination_point.y) * (source_point.x - other.source_point.x)
31
+ td = (source_point.x - destination_point.x) * (other.destination_point.y - source_point.y) + (source_point.y - destination_point.y) * (source_point.x - other.destination_point.x)
32
+ tc * td < 0 && ta * tb < 0
33
+ end
34
+
35
+ def to_s
36
+ "#{source_point}->#{destination_point}"
37
+ end
38
+ end
@@ -0,0 +1,24 @@
1
+ class CfSim::Point
2
+ attr_reader :name, :x, :y
3
+
4
+ def initialize(name, x, y)
5
+ @name = name
6
+ @x, @y = x, y
7
+ end
8
+
9
+ def ==(other)
10
+ eql?(other)
11
+ end
12
+
13
+ def eql?(other)
14
+ @x == other.x && @y == other.y
15
+ end
16
+
17
+ def hash
18
+ @x + @y
19
+ end
20
+
21
+ def to_s
22
+ "#{name}(#{x}, #{y})"
23
+ end
24
+ end
@@ -0,0 +1,36 @@
1
+ require 'forwardable'
2
+
3
+ require 'cf_sim/control_field'
4
+ require 'cf_sim/control_field_set'
5
+
6
+ class CfSim::PointList
7
+ extend Forwardable
8
+ include Enumerable
9
+
10
+ attr_reader :points
11
+ def_delegators :@points, :clear, :each, :empty?, :hash, :size
12
+
13
+ def initialize(*points)
14
+ @points = points.flatten.freeze
15
+ end
16
+
17
+ def max_field_count
18
+ @max_field_count ||= 3 * (points.length - 3) + 1
19
+ end
20
+
21
+ def creatable_field_count
22
+ @creatable_field_count ||= points.combination(3).size
23
+ end
24
+
25
+ def creatable_fields
26
+ @creatable_fields ||= CfSim::ControlFieldSet.new(points.combination(3).map { |a, b, c| CfSim::ControlField.new(a, b, c) })
27
+ end
28
+
29
+ def eql?(other)
30
+ other.class == CfSim::PointList && @points == other.points
31
+ end
32
+
33
+ def ==(other)
34
+ eql?(other)
35
+ end
36
+ end
@@ -0,0 +1,25 @@
1
+ class CfSim::Portal
2
+ attr_reader :name, :latitude, :longitude
3
+
4
+ def initialize(name, latitude, longitude)
5
+ @name = name
6
+ @latitude = latitude
7
+ @longitude = longitude
8
+ end
9
+
10
+ def ==(other)
11
+ eql?(other)
12
+ end
13
+
14
+ def eql?(other)
15
+ @name == other.name && @latitude == other.latitude && @longitude == other.longitude
16
+ end
17
+
18
+ def hash
19
+ @name.hash + @latitude + @longitude
20
+ end
21
+
22
+ def to_s
23
+ "#{name}(#{latitude}, #{longitude})"
24
+ end
25
+ end
@@ -0,0 +1,49 @@
1
+ require 'cblxy'
2
+ require 'cf_sim/cordination_system'
3
+ require 'cf_sim/point'
4
+
5
+ class CfSim::PortalMap
6
+
7
+ attr_reader :portals, :points
8
+
9
+ def initialize(*portals)
10
+ @portals = portals.flatten.dup.freeze
11
+ @cordination_system = CfSim::CordinationSystem.new(@portals.first.latitude, @portals.first.longitude)
12
+ @portal_map = {}
13
+ @point_map = {}
14
+ convert_to_points
15
+ end
16
+
17
+ def find_portal(point)
18
+ @portal_map[point]
19
+ end
20
+
21
+ def find_point(portal)
22
+ @point_map[portal]
23
+ end
24
+
25
+ private
26
+
27
+ def convert_to_points
28
+ @points = []
29
+ @portals.each do |portal|
30
+ point = convert_to_point(portal)
31
+ @points << point
32
+ @portal_map[point] = portal
33
+ @point_map[portal] = point
34
+ end
35
+ @points.freeze
36
+ end
37
+
38
+ def convert_to_point(portal)
39
+ x, y = blxy(convert_point_unit(portal.latitude), convert_point_unit(portal.longitude), @cordination_system.nearest_system_number)
40
+ CfSim::Point.new(portal.name, x, y)
41
+ end
42
+
43
+ # 10進数による座標を、60進数(度分秒)に変換し 10000 倍する
44
+ def convert_point_unit(point_unit)
45
+ degree, rest = point_unit.divmod(1)
46
+ minute, rest = (rest * 60).divmod(1)
47
+ degree * 10000 + minute * 100 + rest * 60
48
+ end
49
+ end
@@ -0,0 +1,3 @@
1
+ module CfSim
2
+ VERSION = "1.0.0"
3
+ end
data/lib/cf_sim.rb ADDED
@@ -0,0 +1,19 @@
1
+ require 'cblxy'
2
+ require 'cf_sim/point'
3
+ require 'cf_sim/portal'
4
+ require 'cf_sim/cordination_system'
5
+ require 'cf_sim/portal_map'
6
+ require 'cf_sim/link'
7
+ require 'cf_sim/control_field'
8
+ require 'cf_sim/control_field_set'
9
+ require 'cf_sim/point_list'
10
+ require 'cf_sim/coexistable_field_map'
11
+ require 'cf_sim/control_field_set_finder'
12
+ require 'cf_sim/intel_map_url_generator'
13
+ require 'cf_sim/data_file_parser'
14
+ require 'cf_sim/version'
15
+ require 'cf_sim/cli'
16
+
17
+ module CfSim
18
+ # Your code goes here...
19
+ end
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cf_sim
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - pinzolo
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-10-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: test-unit
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: coveralls
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: thor
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Propose multi layered control fields pattern by given portals.
84
+ email:
85
+ - pinzolo@gmail.com
86
+ executables:
87
+ - cf_sim
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - ".travis.yml"
93
+ - CODE_OF_CONDUCT.md
94
+ - Gemfile
95
+ - LICENSE
96
+ - README.md
97
+ - Rakefile
98
+ - bin/console
99
+ - bin/setup
100
+ - cf_sim.gemspec
101
+ - exe/cf_sim
102
+ - lib/cblxy.rb
103
+ - lib/cf_sim.rb
104
+ - lib/cf_sim/cli.rb
105
+ - lib/cf_sim/coexistable_field_map.rb
106
+ - lib/cf_sim/control_field.rb
107
+ - lib/cf_sim/control_field_set.rb
108
+ - lib/cf_sim/control_field_set_finder.rb
109
+ - lib/cf_sim/cordination_system.rb
110
+ - lib/cf_sim/data_file_parser.rb
111
+ - lib/cf_sim/intel_map_url_generator.rb
112
+ - lib/cf_sim/link.rb
113
+ - lib/cf_sim/point.rb
114
+ - lib/cf_sim/point_list.rb
115
+ - lib/cf_sim/portal.rb
116
+ - lib/cf_sim/portal_map.rb
117
+ - lib/cf_sim/version.rb
118
+ homepage: https://github.com/pinzolo/cf_sim
119
+ licenses:
120
+ - MIT
121
+ metadata: {}
122
+ post_install_message:
123
+ rdoc_options: []
124
+ require_paths:
125
+ - lib
126
+ required_ruby_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ required_rubygems_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ requirements: []
137
+ rubyforge_project:
138
+ rubygems_version: 2.4.5
139
+ signing_key:
140
+ specification_version: 4
141
+ summary: Multi layered CF simulator
142
+ test_files: []