aixm 0.3.3 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|