aixm 0.3.3 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +1 -2
- data/CHANGELOG.md +20 -0
- data/README.md +7 -2
- data/aixm.gemspec +2 -3
- data/lib/aixm.rb +6 -2
- data/lib/aixm/a.rb +151 -0
- data/lib/aixm/component/frequency.rb +2 -2
- data/lib/aixm/component/geometry.rb +4 -0
- data/lib/aixm/component/geometry/point.rb +0 -4
- data/lib/aixm/component/helipad.rb +8 -22
- data/lib/aixm/component/runway.rb +36 -36
- data/lib/aixm/component/surface.rb +121 -0
- data/lib/aixm/component/timetable.rb +1 -0
- data/lib/aixm/constants.rb +40 -0
- data/lib/aixm/d.rb +5 -0
- data/lib/aixm/document.rb +2 -2
- data/lib/aixm/f.rb +6 -0
- data/lib/aixm/feature/address.rb +100 -0
- data/lib/aixm/feature/airport.rb +26 -7
- data/lib/aixm/feature/airspace.rb +10 -1
- data/lib/aixm/feature/navigational_aid.rb +1 -1
- data/lib/aixm/feature/navigational_aid/designated_point.rb +20 -5
- data/lib/aixm/feature/navigational_aid/dme.rb +2 -2
- data/lib/aixm/{component → feature}/service.rb +67 -16
- data/lib/aixm/feature/unit.rb +40 -6
- data/lib/aixm/refinements.rb +63 -6
- data/lib/aixm/shortcuts.rb +12 -4
- data/lib/aixm/version.rb +1 -1
- data/lib/aixm/xy.rb +6 -1
- data/lib/aixm/z.rb +6 -0
- data/schemas/ofmx/0/OFMX-DataTypes.xsd +5 -2
- data/schemas/ofmx/0/OFMX-Features.xsd +2 -0
- data/spec/factory.rb +32 -10
- data/spec/lib/aixm/a_spec.rb +203 -0
- data/spec/lib/aixm/component/helipad_spec.rb +11 -17
- data/spec/lib/aixm/component/runway_spec.rb +46 -32
- data/spec/lib/aixm/component/surface_spec.rb +88 -0
- data/spec/lib/aixm/d_spec.rb +10 -0
- data/spec/lib/aixm/document_spec.rb +104 -32
- data/spec/lib/aixm/f_spec.rb +10 -0
- data/spec/lib/aixm/feature/address_spec.rb +55 -0
- data/spec/lib/aixm/feature/airport_spec.rb +73 -3
- data/spec/lib/aixm/feature/navigational_aid/designated_point_spec.rb +43 -6
- data/spec/lib/aixm/feature/navigational_aid/dme_spec.rb +2 -2
- data/spec/lib/aixm/feature/navigational_aid/marker_spec.rb +2 -2
- data/spec/lib/aixm/feature/navigational_aid/ndb_spec.rb +2 -2
- data/spec/lib/aixm/feature/navigational_aid/tacan_spec.rb +2 -2
- data/spec/lib/aixm/feature/navigational_aid/vor_spec.rb +6 -6
- data/spec/lib/aixm/{component → feature}/service_spec.rb +12 -14
- data/spec/lib/aixm/feature/unit_spec.rb +7 -4
- data/spec/lib/aixm/refinements_spec.rb +100 -15
- data/spec/lib/aixm/z_spec.rb +10 -0
- metadata +17 -25
- data/lib/aixm/h.rb +0 -87
- data/spec/lib/aixm/h_spec.rb +0 -113
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cbcadda83460463ad9ab68569e04738a5811b10e3534f3f91fde0ed1f4104874
|
4
|
+
data.tar.gz: aa14c72ecf04553fde4243ff74b68e5cfe2b1d3f19efbb4ef1f473a6dce79a38
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 18f3c67e93a4d6527d8240f819c942d82e81cef33332902749ebcde5e62c3aa4aaf2e12ea2ddce4b642b4ba63b2913e557207161dd4400b01685ec673c436885
|
7
|
+
data.tar.gz: f35b079b357d0b00e5c7bc11a71f0e610cc787863eb678f49aa6697ab11eccc32804c33e73e9f2d4851209d9604b16a271c9f85759b2c41b7e8094a928ff5034
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby-2.
|
1
|
+
ruby-2.6.3
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
## 0.3.4
|
2
|
+
|
3
|
+
#### Additions
|
4
|
+
* Address feature
|
5
|
+
* `Runway#preparation`, `Runway#condition` and `Runway#vfr_pattern`
|
6
|
+
* `Service#guessed_unit_type`
|
7
|
+
* Surface for `Runway|Helipad#surface`
|
8
|
+
* Extracted `AIXM::MIN`, `AIXM::SEC` and `AIXM::DMS_RE` to scan for coordinates in texts
|
9
|
+
* Refinement `String#payload_hash`
|
10
|
+
|
11
|
+
#### Breaking Changes
|
12
|
+
* Require Ruby 2.6
|
13
|
+
* Renamed `AIXM::H` to `AIXM::A` (angle) and add simple arithmetics to make it more versatile
|
14
|
+
* `Runway|Helipad#composition` moved to `Runway|Helipad#surface`
|
15
|
+
* DMS notation `{-}{DD}DMMSS{.SS}[NESW]` now requires compulsory cardinal direction (N, E, S or W) at the end
|
16
|
+
|
17
|
+
#### Changes
|
18
|
+
* Service is a feature now
|
19
|
+
|
1
20
|
## 0.3.3
|
2
21
|
|
3
22
|
#### Additions
|
@@ -132,6 +151,7 @@
|
|
132
151
|
## 0.1.0
|
133
152
|
|
134
153
|
#### Initial Implementation
|
154
|
+
* Require Ruby 2.5
|
135
155
|
* `AIXM::XY` (coordinates)
|
136
156
|
* `AIXM::Z` (altitude or elevation)
|
137
157
|
* AIXM-Snapshot 4.5 Document
|
data/README.md
CHANGED
@@ -37,13 +37,15 @@ document.aixm! # not really necessary since AIXM is the default schema
|
|
37
37
|
document.to_xml
|
38
38
|
```
|
39
39
|
|
40
|
-
You can initialize all elements either traditionally or by use of
|
40
|
+
You can initialize all elements either traditionally or by use of the corresponding shorthand AIXM class method. The following two statements are identical:
|
41
41
|
|
42
42
|
```ruby
|
43
43
|
AIXM::Feature::NavigationalAid::DesignatedPoint.new(...)
|
44
44
|
AIXM.designated_point(...)
|
45
45
|
```
|
46
46
|
|
47
|
+
See `AIXM::CLASSES` for the complete list of shorthand names.
|
48
|
+
|
47
49
|
## Configuration
|
48
50
|
|
49
51
|
The following configuration options are available for setting and getting:
|
@@ -76,10 +78,13 @@ AIXM.schema(:version) # => 0
|
|
76
78
|
* [Z (height, elevation or altitude)](http://www.rubydoc.info/gems/aixm/AIXM/Z.html)
|
77
79
|
* [D (distance or length)](http://www.rubydoc.info/gems/aixm/AIXM/D.html)
|
78
80
|
* [F (frequency)](http://www.rubydoc.info/gems/aixm/AIXM/F.html)
|
81
|
+
* [A (angle)](http://www.rubydoc.info/gems/aixm/AIXM/A.html)
|
79
82
|
|
80
83
|
### Features
|
84
|
+
* [Address](http://www.rubydoc.info/gems/aixm/AIXM/Feature/Address.html)
|
81
85
|
* [Organisation](http://www.rubydoc.info/gems/aixm/AIXM/Feature/Organisation.html)
|
82
86
|
* [Unit](http://www.rubydoc.info/gems/aixm/AIXM/Feature/Unit.html)
|
87
|
+
* [Service](http://www.rubydoc.info/gems/aixm/AIXM/Component/Service.html)
|
83
88
|
* [Airport](http://www.rubydoc.info/gems/aixm/AIXM/Feature/Airport.html)
|
84
89
|
* [Airspace](http://www.rubydoc.info/gems/aixm/AIXM/Feature/Airspace.html)
|
85
90
|
* [Navigational aid](http://www.rubydoc.info/gems/aixm/AIXM/NavigationalAid.html)
|
@@ -92,7 +97,6 @@ AIXM.schema(:version) # => 0
|
|
92
97
|
* [Obstacle and obstacle group](http://www.rubydoc.info/gems/aixm/AIXM/Feature/Obstacle.html)
|
93
98
|
|
94
99
|
### Components
|
95
|
-
* [Service](http://www.rubydoc.info/gems/aixm/AIXM/Component/Service.html)
|
96
100
|
* [Frequency](http://www.rubydoc.info/gems/aixm/AIXM/Component/Frequency.html)
|
97
101
|
* [Geometry](http://www.rubydoc.info/gems/aixm/AIXM/Component/Geometry.html)
|
98
102
|
* [Point](http://www.rubydoc.info/gems/aixm/AIXM/Component/Point.html)
|
@@ -101,6 +105,7 @@ AIXM.schema(:version) # => 0
|
|
101
105
|
* [Circle](http://www.rubydoc.info/gems/aixm/AIXM/Component/Circle.html)
|
102
106
|
* [Runway](http://www.rubydoc.info/gems/aixm/AIXM/Component/Runway.html)
|
103
107
|
* [Helipad](http://www.rubydoc.info/gems/aixm/AIXM/Component/Helipad.html)
|
108
|
+
* [Surface](http://www.rubydoc.info/gems/aixm/AIXM/Component/Surface.html)
|
104
109
|
* [Layer](http://www.rubydoc.info/gems/aixm/AIXM/Component/Layer.html)
|
105
110
|
* [Vertical limits](http://www.rubydoc.info/gems/aixm/AIXM/Component/VerticalLimits.html)
|
106
111
|
* [Timetable](http://www.rubydoc.info/gems/aixm/AIXM/Component/Timetable.html)
|
data/aixm.gemspec
CHANGED
@@ -18,9 +18,8 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.required_ruby_version = '>= 2.
|
22
|
-
|
23
|
-
spec.add_development_dependency 'bundler'
|
21
|
+
spec.required_ruby_version = '>= 2.6'
|
22
|
+
|
24
23
|
spec.add_development_dependency 'rake'
|
25
24
|
spec.add_development_dependency 'minitest'
|
26
25
|
spec.add_development_dependency 'minitest-reporters'
|
data/lib/aixm.rb
CHANGED
@@ -5,8 +5,10 @@ require 'nokogiri'
|
|
5
5
|
require 'forwardable'
|
6
6
|
require 'digest'
|
7
7
|
require 'time'
|
8
|
+
require 'pathname'
|
8
9
|
|
9
10
|
require_relative 'aixm/version'
|
11
|
+
require_relative 'aixm/constants'
|
10
12
|
require_relative 'aixm/refinements'
|
11
13
|
require_relative 'aixm/config'
|
12
14
|
require_relative 'aixm/errors'
|
@@ -16,10 +18,9 @@ require_relative 'aixm/xy'
|
|
16
18
|
require_relative 'aixm/z'
|
17
19
|
require_relative 'aixm/d'
|
18
20
|
require_relative 'aixm/f'
|
19
|
-
require_relative 'aixm/
|
21
|
+
require_relative 'aixm/a'
|
20
22
|
|
21
23
|
require_relative 'aixm/component'
|
22
|
-
require_relative 'aixm/component/service'
|
23
24
|
require_relative 'aixm/component/frequency'
|
24
25
|
require_relative 'aixm/component/geometry'
|
25
26
|
require_relative 'aixm/component/geometry/point'
|
@@ -31,10 +32,13 @@ require_relative 'aixm/component/vertical_limits'
|
|
31
32
|
require_relative 'aixm/component/timetable'
|
32
33
|
require_relative 'aixm/component/runway'
|
33
34
|
require_relative 'aixm/component/helipad'
|
35
|
+
require_relative 'aixm/component/surface'
|
34
36
|
|
35
37
|
require_relative 'aixm/feature'
|
38
|
+
require_relative 'aixm/feature/address'
|
36
39
|
require_relative 'aixm/feature/organisation'
|
37
40
|
require_relative 'aixm/feature/unit'
|
41
|
+
require_relative 'aixm/feature/service'
|
38
42
|
require_relative 'aixm/feature/airspace'
|
39
43
|
require_relative 'aixm/feature/airport'
|
40
44
|
require_relative 'aixm/feature/navigational_aid'
|
data/lib/aixm/a.rb
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
using AIXM::Refinements
|
2
|
+
|
3
|
+
module AIXM
|
4
|
+
|
5
|
+
# Angle from 0 to 359 degrees with an optional suffix used for azimuths,
|
6
|
+
# bearings, headings, courses etc.
|
7
|
+
#
|
8
|
+
# @example Initialized with Numeric
|
9
|
+
# a = AIXM.a(12) # 12 degrees, 1 degree precision, no suffix
|
10
|
+
# a.precision # => 3 (three digits = steps of 1 degree)
|
11
|
+
# a.to_s # => "012"
|
12
|
+
# a.suffix # => nil
|
13
|
+
# a.deg # => 12
|
14
|
+
# a.deg += 7 # => 19
|
15
|
+
# a.deg += 341 # => 0 - deg is always within (0..359)
|
16
|
+
# a.to_s # => "000" - to_s is always within ("000".."359")
|
17
|
+
#
|
18
|
+
# @example Initialized with String
|
19
|
+
# a = AIXM.a('06L') # 60 degrees, 10 degree precision, suffix :L
|
20
|
+
# a.precision # => 2 (two digits = steps of 10 degrees)
|
21
|
+
# a.to_s # => "06L"
|
22
|
+
# a.suffix # => :L
|
23
|
+
# a.deg # => 60
|
24
|
+
# a.deg += 7 # => 70
|
25
|
+
# a.deg += 190 # => 0 - deg is always within (0..359)
|
26
|
+
# a.to_s # => "36L" - to_s converts to ("01".."36")
|
27
|
+
class A
|
28
|
+
SUFFIX_INVERSIONS = {
|
29
|
+
R: :L,
|
30
|
+
L: :R
|
31
|
+
}.freeze
|
32
|
+
|
33
|
+
# @return [Integer] angle
|
34
|
+
attr_reader :deg
|
35
|
+
|
36
|
+
# @return [Integer] precision: +2+ (10 degree steps) or +3+ (1 degree steps)
|
37
|
+
attr_reader :precision
|
38
|
+
|
39
|
+
# @return [Symbol, nil] suffix
|
40
|
+
attr_reader :suffix
|
41
|
+
|
42
|
+
def initialize(deg_and_suffix)
|
43
|
+
case deg_and_suffix
|
44
|
+
when Numeric
|
45
|
+
self.deg, @precision = deg_and_suffix, 3
|
46
|
+
when String
|
47
|
+
fail(ArgumentError, "invalid angle") unless deg_and_suffix.to_s =~ /\A(\d+)([A-Z]+)?\z/
|
48
|
+
self.deg, @precision, self.suffix = $1.to_i * 10, 2, $2
|
49
|
+
when Symbol # used only by private build method
|
50
|
+
fail(ArgumentError, "invalid precision") unless %i(2 3).include? deg_and_suffix
|
51
|
+
@deg, @precision = 0, deg_and_suffix.to_s.to_i
|
52
|
+
else
|
53
|
+
fail(ArgumentError, "invalid angle")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return [String]
|
58
|
+
def inspect
|
59
|
+
%Q(#<#{self.class}[precision=#{precision}] #{to_s}>)
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [String] human readable representation according to precision
|
63
|
+
def to_s
|
64
|
+
if precision == 2
|
65
|
+
[('%02d' % ((deg / 10 + 35) % 36 + 1)), suffix].map(&:to_s).join
|
66
|
+
else
|
67
|
+
('%03d' % deg)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def deg=(value)
|
72
|
+
fail(ArgumentError, "invalid deg `#{value}'") unless value.is_a?(Numeric) && value.round.between?(0, 360)
|
73
|
+
@deg = (precision == 2 ? (value.to_f / 10).round * 10 : value.round) % 360
|
74
|
+
end
|
75
|
+
|
76
|
+
def suffix=(value)
|
77
|
+
fail(RuntimeError, "suffix only allowed when precision is 2") unless value.nil? || precision == 2
|
78
|
+
fail(ArgumentError, "invalid suffix") unless value.nil? || value.to_s =~ /\A[A-Z]+\z/
|
79
|
+
@suffix = value&.to_s&.to_sym
|
80
|
+
end
|
81
|
+
|
82
|
+
# Invert an angle by 180 degrees
|
83
|
+
#
|
84
|
+
# @example
|
85
|
+
# AIXM.a(120).invert # => AIXM.a(300)
|
86
|
+
# AIXM.a("34L").invert # => AIXM.a("16R")
|
87
|
+
# AIXM.a("33X").invert # => AIXM.a("33X")
|
88
|
+
#
|
89
|
+
# @return [AIXM::A] inverted angle
|
90
|
+
def invert
|
91
|
+
build(precision: precision, deg: (deg + 180) % 360, suffix: SUFFIX_INVERSIONS.fetch(suffix, suffix))
|
92
|
+
end
|
93
|
+
|
94
|
+
# Check whether +other+ angle is the inverse
|
95
|
+
#
|
96
|
+
# @example
|
97
|
+
# AIXM.a(120).inverse_of? AIXM.a(300) # => true
|
98
|
+
# AIXM.a("34L").inverse_of? AIXM.a("16R") # => true
|
99
|
+
# AIXM.a("33X").inverse_of? AIXM.a("33X") # => true
|
100
|
+
# AIXM.a("16R").inverse_of? AIXM.a("16L") # => false
|
101
|
+
#
|
102
|
+
# @return [Boolean] whether the inverted angle or not
|
103
|
+
def inverse_of?(other)
|
104
|
+
invert == other
|
105
|
+
end
|
106
|
+
|
107
|
+
# Add degrees
|
108
|
+
#
|
109
|
+
# @return [AIXM::A]
|
110
|
+
def +(numeric_or_angle)
|
111
|
+
fail ArgumentError unless numeric_or_angle.respond_to? :round
|
112
|
+
build(precision: precision, deg: (deg + numeric_or_angle.round) % 360, suffix: suffix)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Subtract degrees
|
116
|
+
#
|
117
|
+
# @return [AIXM::A]
|
118
|
+
def -(numeric_or_angle)
|
119
|
+
fail ArgumentError unless numeric_or_angle.respond_to? :round
|
120
|
+
build(precision: precision, deg: (deg - numeric_or_angle.round + 360) % 360, suffix: suffix)
|
121
|
+
end
|
122
|
+
|
123
|
+
# @private
|
124
|
+
def round
|
125
|
+
deg
|
126
|
+
end
|
127
|
+
|
128
|
+
# @see Object#==
|
129
|
+
# @return [Boolean]
|
130
|
+
def ==(other)
|
131
|
+
self.class === other && deg == other.deg && precision == other.precision && suffix == other.suffix
|
132
|
+
end
|
133
|
+
alias_method :eql?, :==
|
134
|
+
|
135
|
+
# @see Object#hash
|
136
|
+
# @return [Integer]
|
137
|
+
def hash
|
138
|
+
to_s.hash
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
def build(precision:, deg:, suffix: nil)
|
144
|
+
self.class.new(precision.to_s.to_sym).tap do |a|
|
145
|
+
a.deg = deg
|
146
|
+
a.suffix = suffix
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
@@ -32,7 +32,7 @@ module AIXM
|
|
32
32
|
OTHER: :other # specify in remarks
|
33
33
|
}.freeze
|
34
34
|
|
35
|
-
# @return [AIXM::
|
35
|
+
# @return [AIXM::Feature::Service] service the frequency belongs to
|
36
36
|
attr_reader :service
|
37
37
|
|
38
38
|
# @return [AIXM::F] frequency for transmission (outgoing)
|
@@ -69,7 +69,7 @@ module AIXM
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def service=(value)
|
72
|
-
fail(ArgumentError, "invalid service") unless value.is_a? AIXM::
|
72
|
+
fail(ArgumentError, "invalid service") unless value.is_a? AIXM::Feature::Service
|
73
73
|
@service = value
|
74
74
|
end
|
75
75
|
private :service=
|
@@ -13,25 +13,12 @@ module AIXM
|
|
13
13
|
# helipad.z = AIXM.z or nil
|
14
14
|
# helipad.length = AIXM.d or nil # must use same unit as width
|
15
15
|
# helipad.width = AIXM.d or nil # must use same unit as length
|
16
|
-
# helipad.
|
16
|
+
# helipad.surface = AIXM.surface
|
17
17
|
# helipad.status = STATUSES or nil
|
18
18
|
# helipad.remarks = String or nil
|
19
19
|
#
|
20
20
|
# @see https://github.com/openflightmaps/ofmx/wiki/Airport#tla-helipad-tlof
|
21
21
|
class Helipad
|
22
|
-
COMPOSITIONS = {
|
23
|
-
ASPH: :asphalt,
|
24
|
-
BITUM: :bitumen, # dug up, bound and rolled ground
|
25
|
-
CONC: :concrete,
|
26
|
-
GRAVE: :gravel, # small and midsize rounded stones
|
27
|
-
MACADAM: :macadam, # small rounded stones
|
28
|
-
SAND: :sand,
|
29
|
-
GRADE: :graded_earth, # graded or rolled earth possibly with some grass
|
30
|
-
GRASS: :grass, # lawn
|
31
|
-
WATER: :water,
|
32
|
-
OTHER: :other # specify in remarks
|
33
|
-
}.freeze
|
34
|
-
|
35
22
|
STATUSES = {
|
36
23
|
CLSD: :closed,
|
37
24
|
WIP: :work_in_progress, # e.g. construction work
|
@@ -59,8 +46,8 @@ module AIXM
|
|
59
46
|
# @return [AIXM::D, nil] width
|
60
47
|
attr_reader :width
|
61
48
|
|
62
|
-
# @return [
|
63
|
-
attr_reader :
|
49
|
+
# @return [AIXM::Component::Surface] surface of the helipad
|
50
|
+
attr_reader :surface
|
64
51
|
|
65
52
|
# @return [Symbol, nil] status of the helipad (see {STATUSES}) or +nil+ for normal operation
|
66
53
|
attr_reader :status
|
@@ -70,11 +57,12 @@ module AIXM
|
|
70
57
|
|
71
58
|
def initialize(name:)
|
72
59
|
self.name = name
|
60
|
+
@surface = AIXM.surface
|
73
61
|
end
|
74
62
|
|
75
63
|
# @return [String]
|
76
64
|
def inspect
|
77
|
-
%Q(#<#{self.class} name=#{name.inspect}>)
|
65
|
+
%Q(#<#{self.class} airport=#{airport&.id.inspect} name=#{name.inspect}>)
|
78
66
|
end
|
79
67
|
|
80
68
|
def airport=(value)
|
@@ -114,10 +102,6 @@ module AIXM
|
|
114
102
|
end
|
115
103
|
end
|
116
104
|
|
117
|
-
def composition=(value)
|
118
|
-
@composition = value.nil? ? nil : COMPOSITIONS.lookup(value.to_s.to_sym, nil) || fail(ArgumentError, "invalid composition")
|
119
|
-
end
|
120
|
-
|
121
105
|
def status=(value)
|
122
106
|
@status = value.nil? ? nil : (STATUSES.lookup(value.to_s.to_sym, nil) || fail(ArgumentError, "invalid status"))
|
123
107
|
end
|
@@ -151,7 +135,9 @@ module AIXM
|
|
151
135
|
tla.valWid(width.dist.trim) if width
|
152
136
|
tla.uomDim(length.unit.to_s.upcase) if length
|
153
137
|
tla.uomDim(width.unit.to_s.upcase) if width && !length
|
154
|
-
|
138
|
+
unless (xml = surface.to_xml).empty?
|
139
|
+
tla << xml.indent(2)
|
140
|
+
end
|
155
141
|
tla.codeSts(STATUSES.key(status).to_s) if status
|
156
142
|
tla.txtRmk(remarks) if remarks
|
157
143
|
end
|
@@ -18,14 +18,15 @@ module AIXM
|
|
18
18
|
# )
|
19
19
|
# runway.length = AIXM.d or nil # must use same unit as width
|
20
20
|
# runway.width = AIXM.d or nil # must use same unit as length
|
21
|
-
# runway.
|
21
|
+
# runway.surface = AIXM.surface
|
22
22
|
# runway.status = STATUSES or nil
|
23
23
|
# runway.remarks = String or nil
|
24
|
-
# runway.forth.name = AIXM.
|
25
|
-
# runway.forth.geographic_orientation =
|
24
|
+
# runway.forth.name = AIXM.a[precision=2] # preset based on the runway name
|
25
|
+
# runway.forth.geographic_orientation = AIXM.a[precision=3] or nil
|
26
26
|
# runway.forth.xy = AIXM.xy
|
27
27
|
# runway.forth.z = AIXM.z or nil
|
28
28
|
# runway.forth.displaced_threshold = AIXM.xy or AIXM.d or nil
|
29
|
+
# runway.forth.vfr_pattern = VFR_PATTERNS or nil
|
29
30
|
# runway.forth.remarks = String or nil
|
30
31
|
#
|
31
32
|
# @example Bidirectional runway
|
@@ -45,19 +46,6 @@ module AIXM
|
|
45
46
|
#
|
46
47
|
# @see https://github.com/openflightmaps/ofmx/wiki/Airport#rwy-runway
|
47
48
|
class Runway
|
48
|
-
COMPOSITIONS = {
|
49
|
-
ASPH: :asphalt,
|
50
|
-
BITUM: :bitumen, # dug up, bound and rolled ground
|
51
|
-
CONC: :concrete,
|
52
|
-
GRAVE: :gravel, # small and midsize rounded stones
|
53
|
-
MACADAM: :macadam, # small rounded stones
|
54
|
-
SAND: :sand,
|
55
|
-
GRADE: :graded_earth, # graded or rolled earth possibly with some grass
|
56
|
-
GRASS: :grass, # lawn
|
57
|
-
WATER: :water,
|
58
|
-
OTHER: :other # specify in remarks
|
59
|
-
}
|
60
|
-
|
61
49
|
STATUSES = {
|
62
50
|
CLSD: :closed,
|
63
51
|
WIP: :work_in_progress, # e.g. construction work
|
@@ -79,8 +67,8 @@ module AIXM
|
|
79
67
|
# @return [AIXM::D, nil] width
|
80
68
|
attr_reader :width
|
81
69
|
|
82
|
-
# @return [
|
83
|
-
attr_reader :
|
70
|
+
# @return [AIXM::Component::Surface] surface of the runway
|
71
|
+
attr_reader :surface
|
84
72
|
|
85
73
|
# @return [Symbol, nil] status of the runway (see {STATUSES}) or +nil+ for normal operation
|
86
74
|
attr_reader :status
|
@@ -96,16 +84,17 @@ module AIXM
|
|
96
84
|
|
97
85
|
def initialize(name:)
|
98
86
|
self.name = name
|
99
|
-
@name.split(
|
100
|
-
@forth = Direction.new(runway: self, name: AIXM.
|
101
|
-
@back = Direction.new(runway: self, name: AIXM.
|
87
|
+
@name.split("/").tap do |forth, back|
|
88
|
+
@forth = Direction.new(runway: self, name: AIXM.a(forth))
|
89
|
+
@back = Direction.new(runway: self, name: AIXM.a(back)) if back
|
102
90
|
fail(ArgumentError, "invalid name") unless !@back || @back.name.inverse_of?(@forth.name)
|
103
91
|
end
|
92
|
+
@surface = AIXM.surface
|
104
93
|
end
|
105
94
|
|
106
95
|
# @return [String]
|
107
96
|
def inspect
|
108
|
-
%Q(#<#{self.class} name=#{name.inspect}>)
|
97
|
+
%Q(#<#{self.class} airport=#{airport&.id.inspect} name=#{name.inspect}>)
|
109
98
|
end
|
110
99
|
|
111
100
|
def airport=(value)
|
@@ -135,10 +124,6 @@ module AIXM
|
|
135
124
|
end
|
136
125
|
end
|
137
126
|
|
138
|
-
def composition=(value)
|
139
|
-
@composition = value.nil? ? nil : COMPOSITIONS.lookup(value.to_s.to_sym, nil) || fail(ArgumentError, "invalid composition")
|
140
|
-
end
|
141
|
-
|
142
127
|
def status=(value)
|
143
128
|
@status = value.nil? ? nil : (STATUSES.lookup(value.to_s.to_sym, nil) || fail(ArgumentError, "invalid status"))
|
144
129
|
end
|
@@ -165,7 +150,9 @@ module AIXM
|
|
165
150
|
rwy.valWid(width.dist.trim) if width
|
166
151
|
rwy.uomDimRwy(length.unit.to_s.upcase) if length
|
167
152
|
rwy.uomDimRwy(width.unit.to_s.upcase) if width && !length
|
168
|
-
|
153
|
+
unless (xml = surface.to_xml).empty?
|
154
|
+
rwy << xml.indent(2)
|
155
|
+
end
|
169
156
|
rwy.codeSts(STATUSES.key(status).to_s) if status
|
170
157
|
rwy.txtRmk(remarks) if remarks
|
171
158
|
end
|
@@ -181,13 +168,19 @@ module AIXM
|
|
181
168
|
#
|
182
169
|
# @see https://github.com/openflightmaps/ofmx/wiki/Airport#rdn-runway-direction
|
183
170
|
class Direction
|
171
|
+
VFR_PATTERNS = {
|
172
|
+
L: :left,
|
173
|
+
R: :right,
|
174
|
+
E: :left_or_right
|
175
|
+
}
|
176
|
+
|
184
177
|
# @return [AIXM::Component::Runway] runway the runway direction is further describing
|
185
178
|
attr_reader :runway
|
186
179
|
|
187
|
-
# @return [AIXM::
|
180
|
+
# @return [AIXM::A] partial name of runway (e.g. "12" or "16L")
|
188
181
|
attr_reader :name
|
189
182
|
|
190
|
-
# @return [
|
183
|
+
# @return [AIXM::A, nil] geographic orientation (true bearing) in degrees
|
191
184
|
attr_reader :geographic_orientation
|
192
185
|
|
193
186
|
# @return [AIXM::XY] beginning point (middle of the runway width)
|
@@ -201,6 +194,9 @@ module AIXM
|
|
201
194
|
# point
|
202
195
|
attr_reader :displaced_threshold
|
203
196
|
|
197
|
+
# @return [Symbol, nil] direction of the VFR flight pattern (see {VFR_PATTERNS})
|
198
|
+
attr_reader :vfr_pattern
|
199
|
+
|
204
200
|
# @return [String, nil] free text remarks
|
205
201
|
attr_reader :remarks
|
206
202
|
|
@@ -210,7 +206,7 @@ module AIXM
|
|
210
206
|
|
211
207
|
# @return [String]
|
212
208
|
def inspect
|
213
|
-
%Q(#<#{self.class} name=#{name.inspect}>)
|
209
|
+
%Q(#<#{self.class} airport=#{runway&.airport&.id.inspect} name=#{name.inspect}>)
|
214
210
|
end
|
215
211
|
|
216
212
|
def runway=(value)
|
@@ -220,15 +216,14 @@ module AIXM
|
|
220
216
|
private :runway
|
221
217
|
|
222
218
|
def name=(value)
|
223
|
-
fail(ArgumentError, "invalid name") unless value.is_a? AIXM::
|
219
|
+
fail(ArgumentError, "invalid name") unless value.is_a? AIXM::A
|
224
220
|
@name = value
|
225
221
|
end
|
226
222
|
|
227
223
|
def geographic_orientation=(value)
|
228
224
|
return @geographic_orientation = nil if value.nil?
|
229
|
-
fail(ArgumentError, "invalid geographic orientation") unless value.is_a?
|
230
|
-
@geographic_orientation = value
|
231
|
-
fail(ArgumentError, "invalid geographic orientation") unless (1..360).include? @geographic_orientation
|
225
|
+
fail(ArgumentError, "invalid geographic orientation") unless value.is_a? AIXM::A
|
226
|
+
@geographic_orientation = value
|
232
227
|
end
|
233
228
|
|
234
229
|
def xy=(value)
|
@@ -255,14 +250,18 @@ module AIXM
|
|
255
250
|
end
|
256
251
|
end
|
257
252
|
|
253
|
+
def vfr_pattern=(value)
|
254
|
+
@vfr_pattern = value.nil? ? nil : (VFR_PATTERNS.lookup(value.to_s.to_sym, nil) || fail(ArgumentError, "invalid VFR pattern"))
|
255
|
+
end
|
256
|
+
|
258
257
|
def remarks=(value)
|
259
258
|
@remarks = value&.to_s
|
260
259
|
end
|
261
260
|
|
262
|
-
# @return [
|
261
|
+
# @return [AIXM::A] magnetic orientation (magnetic bearing) in degrees
|
263
262
|
def magnetic_orientation
|
264
263
|
if geographic_orientation && runway.airport.declination
|
265
|
-
|
264
|
+
geographic_orientation + runway.airport.declination
|
266
265
|
end
|
267
266
|
end
|
268
267
|
|
@@ -282,6 +281,7 @@ module AIXM
|
|
282
281
|
rdn.valElevTdz(z.alt)
|
283
282
|
rdn.uomElevTdz(z.unit.upcase.to_s)
|
284
283
|
end
|
284
|
+
rdn.codeVfrPattern(VFR_PATTERNS.key(vfr_pattern).to_s) if vfr_pattern
|
285
285
|
rdn.txtRmk(remarks) if remarks
|
286
286
|
end
|
287
287
|
if displaced_threshold
|