aixm 1.0.0 → 1.1.0
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
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +43 -13
- data/README.md +31 -20
- data/lib/aixm/a.rb +89 -71
- data/lib/aixm/association.rb +37 -27
- data/lib/aixm/classes.rb +5 -2
- data/lib/aixm/{feature → component}/address.rb +12 -9
- data/lib/aixm/component/approach_lighting.rb +136 -0
- data/lib/aixm/component/fato.rb +58 -42
- data/lib/aixm/component/frequency.rb +2 -2
- data/lib/aixm/component/geometry/arc.rb +1 -1
- data/lib/aixm/component/geometry/border.rb +1 -1
- data/lib/aixm/component/geometry/circle.rb +3 -3
- data/lib/aixm/component/geometry/point.rb +1 -1
- data/lib/aixm/component/geometry/rhumb_line.rb +1 -1
- data/lib/aixm/component/geometry.rb +3 -2
- data/lib/aixm/component/helipad.rb +26 -36
- data/lib/aixm/component/layer.rb +5 -3
- data/lib/aixm/component/lighting.rb +5 -5
- data/lib/aixm/component/runway.rb +81 -52
- data/lib/aixm/component/service.rb +12 -3
- data/lib/aixm/component/surface.rb +12 -12
- data/lib/aixm/component/timetable.rb +2 -2
- data/lib/aixm/component/vasis.rb +105 -0
- data/lib/aixm/component/vertical_limit.rb +3 -3
- data/lib/aixm/component.rb +10 -0
- data/lib/aixm/config.rb +2 -0
- data/lib/aixm/d.rb +16 -15
- data/lib/aixm/document.rb +10 -1
- data/lib/aixm/f.rb +1 -1
- data/lib/aixm/feature/airport.rb +34 -10
- data/lib/aixm/feature/airspace.rb +3 -0
- data/lib/aixm/feature/navigational_aid/dme.rb +29 -10
- data/lib/aixm/feature/navigational_aid/marker.rb +2 -2
- data/lib/aixm/feature/navigational_aid/tacan.rb +3 -2
- data/lib/aixm/feature/navigational_aid/vor.rb +32 -13
- data/lib/aixm/feature/navigational_aid.rb +1 -1
- data/lib/aixm/feature/obstacle.rb +6 -6
- data/lib/aixm/feature/obstacle_group.rb +6 -2
- data/lib/aixm/feature/organisation.rb +1 -0
- data/lib/aixm/feature/unit.rb +2 -1
- data/lib/aixm/feature.rb +3 -0
- data/lib/aixm/memoize.rb +27 -11
- data/lib/aixm/p.rb +3 -2
- data/lib/aixm/payload_hash.rb +1 -1
- data/lib/aixm/r.rb +62 -0
- data/lib/aixm/refinements.rb +4 -4
- data/lib/aixm/version.rb +1 -1
- data/lib/aixm/w.rb +2 -1
- data/lib/aixm/xy.rb +1 -1
- data/lib/aixm/z.rb +5 -4
- data/lib/aixm.rb +10 -5
- data/schemas/ofmx/0.1/OFMX-DataTypes.xsd +6 -0
- data/schemas/ofmx/0.1/OFMX-Snapshot.xsd +5 -0
- data.tar.gz.sig +0 -0
- metadata +8 -4
- metadata.gz.sig +0 -0
@@ -1,7 +1,7 @@
|
|
1
1
|
using AIXM::Refinements
|
2
2
|
|
3
3
|
module AIXM
|
4
|
-
|
4
|
+
class Component
|
5
5
|
|
6
6
|
# Runways are landing and takeoff strips for forward propelled aircraft.
|
7
7
|
#
|
@@ -16,16 +16,19 @@ module AIXM
|
|
16
16
|
# runway = AIXM.runway(
|
17
17
|
# name: String
|
18
18
|
# )
|
19
|
-
# runway.
|
20
|
-
# runway.width = AIXM.d or nil # must use same unit as length
|
19
|
+
# runway.dimensions = AIXM.r or nil
|
21
20
|
# runway.surface = AIXM.surface
|
21
|
+
# runway.marking = String or nil
|
22
22
|
# runway.status = STATUSES or nil
|
23
23
|
# runway.remarks = String or nil
|
24
|
-
# runway.forth.name = AIXM.a
|
25
|
-
# runway.forth.
|
24
|
+
# runway.forth.name = AIXM.a # preset based on the runway name
|
25
|
+
# runway.forth.geographic_bearing = AIXM.a or nil
|
26
26
|
# runway.forth.xy = AIXM.xy
|
27
|
-
# runway.forth.z = AIXM.z or nil
|
27
|
+
# runway.forth.z = AIXM.z or nil # highest point of the TDZ
|
28
28
|
# runway.forth.displaced_threshold = AIXM.xy or AIXM.d or nil
|
29
|
+
# runway.forth.vasis = AIXM.vasis or nil (default: unspecified VASIS)
|
30
|
+
# runway.forth.add_lighting = AIXM.lighting
|
31
|
+
# runway.forth.add_approach_lighting = AIXM.approach_lighting
|
29
32
|
# runway.forth.vfr_pattern = VFR_PATTERNS or nil
|
30
33
|
# runway.forth.remarks = String or nil
|
31
34
|
#
|
@@ -33,19 +36,19 @@ module AIXM
|
|
33
36
|
# runway = AIXM.runway(name: '16L/34R')
|
34
37
|
# runway.name # => '16L/34R'
|
35
38
|
# runway.forth.name.to_s = '16L'
|
36
|
-
# runway.forth.
|
39
|
+
# runway.forth.geographic_bearing = 165
|
37
40
|
# runway.back.name.to_s = '34R'
|
38
|
-
# runway.back.
|
41
|
+
# runway.back.geographic_bearing = 345
|
39
42
|
#
|
40
43
|
# @example Unidirectional runway:
|
41
44
|
# runway = AIXM.runway(name: '16L')
|
42
45
|
# runway.name # => '16L'
|
43
46
|
# runway.forth.name.to_s = '16L'
|
44
|
-
# runway.forth.
|
47
|
+
# runway.forth.geographic_bearing = 165
|
45
48
|
# runway.back = nil
|
46
49
|
#
|
47
50
|
# @see https://gitlab.com/openflightmaps/ofmx/wikis/Airport#rwy-runway
|
48
|
-
class Runway
|
51
|
+
class Runway < Component
|
49
52
|
include AIXM::Association
|
50
53
|
include AIXM::Memoize
|
51
54
|
|
@@ -56,20 +59,29 @@ module AIXM
|
|
56
59
|
FAILAID: :visual_aids_failure, # failure or irregular operation of visual aids
|
57
60
|
SPOWER: :secondary_power, # secondary power supply in operation
|
58
61
|
OTHER: :other # specify in remarks
|
59
|
-
}
|
62
|
+
}.freeze
|
60
63
|
|
61
64
|
# @!method forth
|
62
65
|
# @return [AIXM::Component::Runway::Direction] main direction
|
66
|
+
#
|
63
67
|
# @!method forth=(forth)
|
64
68
|
# @param forth [AIXM::Component::Runway::Direction]
|
65
69
|
has_one :forth, accept: 'AIXM::Component::Runway::Direction'
|
66
70
|
|
67
71
|
# @!method back
|
68
72
|
# @return [AIXM::Component::Runway::Direction, nil] reverse direction
|
73
|
+
#
|
69
74
|
# @!method back=(back)
|
70
75
|
# @param back [AIXM::Component::Runway::Direction, nil]
|
71
76
|
has_one :back, accept: 'AIXM::Component::Runway::Direction', allow_nil: true
|
72
77
|
|
78
|
+
# @!method surface
|
79
|
+
# @return [AIXM::Component::Surface] surface of the runway
|
80
|
+
#
|
81
|
+
# @!method surface=(surface)
|
82
|
+
# @param surface [AIXM::Component::Surface]
|
83
|
+
has_one :surface, accept: 'AIXM::Component::Surface'
|
84
|
+
|
73
85
|
# @!method airport
|
74
86
|
# @return [AIXM::Feature::Airport] airport the runway belongs to
|
75
87
|
belongs_to :airport
|
@@ -77,14 +89,11 @@ module AIXM
|
|
77
89
|
# @return [String] full name of runway (e.g. "12/30" or "16L/34R")
|
78
90
|
attr_reader :name
|
79
91
|
|
80
|
-
# @return [AIXM::
|
81
|
-
attr_reader :
|
92
|
+
# @return [AIXM::R, nil] dimensions
|
93
|
+
attr_reader :dimensions
|
82
94
|
|
83
|
-
# @return [
|
84
|
-
attr_reader :
|
85
|
-
|
86
|
-
# @return [AIXM::Component::Surface] surface of the runway
|
87
|
-
attr_reader :surface
|
95
|
+
# @return [String, nil] markings
|
96
|
+
attr_reader :marking
|
88
97
|
|
89
98
|
# @return [Symbol, nil] status of the runway (see {STATUSES}) or +nil+ for normal operation
|
90
99
|
attr_reader :status
|
@@ -99,7 +108,7 @@ module AIXM
|
|
99
108
|
self.back = Direction.new(name: AIXM.a(back_name)) if back_name
|
100
109
|
fail(ArgumentError, "invalid name") unless !back || back.name.inverse_of?(@forth.name)
|
101
110
|
end
|
102
|
-
|
111
|
+
self.surface = AIXM.surface
|
103
112
|
end
|
104
113
|
|
105
114
|
# @return [String]
|
@@ -112,20 +121,13 @@ module AIXM
|
|
112
121
|
@name = value.uptrans
|
113
122
|
end
|
114
123
|
|
115
|
-
def
|
116
|
-
|
117
|
-
|
118
|
-
fail(ArgumentError, "invalid length unit") if width && width.unit != value.unit
|
119
|
-
value
|
120
|
-
end
|
124
|
+
def dimensions=(value)
|
125
|
+
fail(ArgumentError, "invalid dimensions") unless value.nil? || value.is_a?(AIXM::R)
|
126
|
+
@dimensions = value
|
121
127
|
end
|
122
128
|
|
123
|
-
def
|
124
|
-
@
|
125
|
-
fail(ArgumentError, "invalid width") unless value.is_a?(AIXM::D) && value.dist > 0
|
126
|
-
fail(ArgumentError, "invalid width unit") if length && length.unit != value.unit
|
127
|
-
value
|
128
|
-
end
|
129
|
+
def marking=(value)
|
130
|
+
@marking = value&.to_s
|
129
131
|
end
|
130
132
|
|
131
133
|
def status=(value)
|
@@ -151,14 +153,16 @@ module AIXM
|
|
151
153
|
builder = Builder::XmlMarkup.new(indent: 2)
|
152
154
|
builder.Rwy do |rwy|
|
153
155
|
rwy << to_uid.indent(2)
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
156
|
+
if dimensions
|
157
|
+
rwy.valLen(dimensions.length.to_m.dim.trim)
|
158
|
+
rwy.valWid(dimensions.width.to_m.dim.trim)
|
159
|
+
rwy.uomDimRwy('M')
|
160
|
+
end
|
158
161
|
unless (xml = surface.to_xml).empty?
|
159
162
|
rwy << xml.indent(2)
|
160
163
|
end
|
161
164
|
rwy.codeSts(STATUSES.key(status).to_s) if status
|
165
|
+
rwy.txtMarking(marking) if marking
|
162
166
|
rwy.txtRmk(remarks) if remarks
|
163
167
|
end
|
164
168
|
%i(@forth @back).each do |direction|
|
@@ -181,15 +185,24 @@ module AIXM
|
|
181
185
|
L: :left,
|
182
186
|
R: :right,
|
183
187
|
E: :left_or_right
|
184
|
-
}
|
188
|
+
}.freeze
|
185
189
|
|
186
190
|
# @!method lightings
|
187
191
|
# @return [Array<AIXM::Component::Lighting>] installed lighting systems
|
192
|
+
#
|
188
193
|
# @!method add_lighting(lighting)
|
189
194
|
# @param lighting [AIXM::Component::Lighting]
|
190
195
|
# @return [self]
|
191
196
|
has_many :lightings, as: :lightable
|
192
197
|
|
198
|
+
# @!method approach_lightings
|
199
|
+
# @return [Array<AIXM::Component::ApproachLighting>] installed approach lighting systems
|
200
|
+
#
|
201
|
+
# @!method add_approach_lighting(approach_lighting)
|
202
|
+
# @param approach_lighting [AIXM::Component::ApproachLighting]
|
203
|
+
# @return [self]
|
204
|
+
has_many :approach_lightings, as: :approach_lightable
|
205
|
+
|
193
206
|
# @!method runway
|
194
207
|
# @return [AIXM::Component::Runway] runway the runway direction is further describing
|
195
208
|
belongs_to :runway, readonly: true
|
@@ -197,8 +210,8 @@ module AIXM
|
|
197
210
|
# @return [AIXM::A] partial name of runway (e.g. "12" or "16L")
|
198
211
|
attr_reader :name
|
199
212
|
|
200
|
-
# @return [AIXM::A, nil]
|
201
|
-
attr_reader :
|
213
|
+
# @return [AIXM::A, nil] (true) geographic bearing in degrees
|
214
|
+
attr_reader :geographic_bearing
|
202
215
|
|
203
216
|
# @return [AIXM::XY] beginning point (middle of the runway width)
|
204
217
|
attr_reader :xy
|
@@ -211,6 +224,10 @@ module AIXM
|
|
211
224
|
# point
|
212
225
|
attr_reader :displaced_threshold
|
213
226
|
|
227
|
+
# @return [AIXM::Component::VASIS, nil] visual approach slope indicator
|
228
|
+
# system
|
229
|
+
attr_reader :vasis
|
230
|
+
|
214
231
|
# @return [Symbol, nil] direction of the VFR flight pattern (see {VFR_PATTERNS})
|
215
232
|
attr_reader :vfr_pattern
|
216
233
|
|
@@ -219,11 +236,12 @@ module AIXM
|
|
219
236
|
|
220
237
|
def initialize(name:)
|
221
238
|
self.name = name
|
239
|
+
self.vasis = AIXM.vasis
|
222
240
|
end
|
223
241
|
|
224
242
|
# @return [String]
|
225
243
|
def inspect
|
226
|
-
%Q(#<#{self.class} airport=#{runway&.airport&.id.inspect} name=#{name.inspect}>)
|
244
|
+
%Q(#<#{self.class} airport=#{runway&.airport&.id.inspect} name=#{name.to_s(:runway).inspect}>)
|
227
245
|
end
|
228
246
|
|
229
247
|
def name=(value)
|
@@ -231,10 +249,10 @@ module AIXM
|
|
231
249
|
@name = value
|
232
250
|
end
|
233
251
|
|
234
|
-
def
|
235
|
-
return @
|
236
|
-
fail(ArgumentError, "invalid geographic
|
237
|
-
@
|
252
|
+
def geographic_bearing=(value)
|
253
|
+
return @geographic_bearing = nil if value.nil?
|
254
|
+
fail(ArgumentError, "invalid geographic bearing") unless value.is_a? AIXM::A
|
255
|
+
@geographic_bearing = value
|
238
256
|
end
|
239
257
|
|
240
258
|
def xy=(value)
|
@@ -252,7 +270,7 @@ module AIXM
|
|
252
270
|
when AIXM::XY
|
253
271
|
@displaced_threshold = @xy.distance(value)
|
254
272
|
when AIXM::D
|
255
|
-
fail(ArgumentError, "invalid displaced threshold") unless value.
|
273
|
+
fail(ArgumentError, "invalid displaced threshold") unless value.dim > 0
|
256
274
|
@displaced_threshold = value
|
257
275
|
when NilClass
|
258
276
|
@displaced_threshold = nil
|
@@ -261,6 +279,11 @@ module AIXM
|
|
261
279
|
end
|
262
280
|
end
|
263
281
|
|
282
|
+
def vasis=(value)
|
283
|
+
fail(ArgumentError, "invalid vasis") unless value.nil? || value.is_a?(AIXM::Component::VASIS)
|
284
|
+
@vasis = value
|
285
|
+
end
|
286
|
+
|
264
287
|
def vfr_pattern=(value)
|
265
288
|
@vfr_pattern = value.nil? ? nil : (VFR_PATTERNS.lookup(value.to_s.to_sym, nil) || fail(ArgumentError, "invalid VFR pattern"))
|
266
289
|
end
|
@@ -269,10 +292,10 @@ module AIXM
|
|
269
292
|
@remarks = value&.to_s
|
270
293
|
end
|
271
294
|
|
272
|
-
# @return [AIXM::A] magnetic
|
273
|
-
def
|
274
|
-
if
|
275
|
-
|
295
|
+
# @return [AIXM::A] magnetic bearing in degrees
|
296
|
+
def magnetic_bearing
|
297
|
+
if geographic_bearing && runway.airport.declination
|
298
|
+
geographic_bearing - runway.airport.declination
|
276
299
|
end
|
277
300
|
end
|
278
301
|
|
@@ -281,7 +304,7 @@ module AIXM
|
|
281
304
|
builder = Builder::XmlMarkup.new(indent: 2)
|
282
305
|
builder.RdnUid do |rdn_uid|
|
283
306
|
rdn_uid << runway.to_uid.indent(2)
|
284
|
-
rdn_uid.txtDesig(name)
|
307
|
+
rdn_uid.txtDesig(name.to_s(:runway))
|
285
308
|
end
|
286
309
|
end
|
287
310
|
memoize :to_uid
|
@@ -293,12 +316,15 @@ module AIXM
|
|
293
316
|
rdn << to_uid.indent(2)
|
294
317
|
rdn.geoLat(xy.lat(AIXM.schema))
|
295
318
|
rdn.geoLong(xy.long(AIXM.schema))
|
296
|
-
rdn.valTrueBrg(
|
297
|
-
rdn.valMagBrg(
|
319
|
+
rdn.valTrueBrg(geographic_bearing.to_s(:bearing)) if geographic_bearing
|
320
|
+
rdn.valMagBrg(magnetic_bearing.to_s(:bearing)) if magnetic_bearing
|
298
321
|
if z
|
299
322
|
rdn.valElevTdz(z.alt)
|
300
323
|
rdn.uomElevTdz(z.unit.upcase.to_s)
|
301
324
|
end
|
325
|
+
if vasis
|
326
|
+
rdn << vasis.to_xml.indent(2)
|
327
|
+
end
|
302
328
|
rdn.codeVfrPattern(VFR_PATTERNS.key(vfr_pattern).to_s) if vfr_pattern
|
303
329
|
rdn.txtRmk(remarks) if remarks
|
304
330
|
end
|
@@ -309,7 +335,7 @@ module AIXM
|
|
309
335
|
rdd_uid.codeType('DPLM')
|
310
336
|
rdd_uid.codeDayPeriod('A')
|
311
337
|
end
|
312
|
-
rdd.valDist(displaced_threshold.
|
338
|
+
rdd.valDist(displaced_threshold.dim.trim)
|
313
339
|
rdd.uomDist(displaced_threshold.unit.to_s.upcase)
|
314
340
|
rdd.txtRmk(remarks) if remarks
|
315
341
|
end
|
@@ -317,6 +343,9 @@ module AIXM
|
|
317
343
|
lightings.each do |lighting|
|
318
344
|
builder << lighting.to_xml(as: :Rls)
|
319
345
|
end
|
346
|
+
approach_lightings.each do |approach_lighting|
|
347
|
+
builder << approach_lighting.to_xml(as: :Rda)
|
348
|
+
end
|
320
349
|
builder.target!
|
321
350
|
end
|
322
351
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
using AIXM::Refinements
|
2
2
|
|
3
3
|
module AIXM
|
4
|
-
|
4
|
+
class Component
|
5
5
|
|
6
6
|
# Service provided by a unit.
|
7
7
|
#
|
@@ -14,7 +14,7 @@ module AIXM
|
|
14
14
|
# service.add_frequency(AIXM.frequency)
|
15
15
|
#
|
16
16
|
# @see https://gitlab.com/openflightmaps/ofmx/wikis/Organisation#ser-service
|
17
|
-
class Service
|
17
|
+
class Service < Component
|
18
18
|
include AIXM::Association
|
19
19
|
include AIXM::Memoize
|
20
20
|
|
@@ -73,7 +73,7 @@ module AIXM
|
|
73
73
|
TWR: :aerodrome_control_tower_service,
|
74
74
|
UAC: :upper_area_control_service,
|
75
75
|
UDF: :uhf_direction_finding_service,
|
76
|
-
VDF: :
|
76
|
+
VDF: :vdf_direction_finding_service,
|
77
77
|
VOLMET: :volmet_service,
|
78
78
|
VOT: :vor_test_facility,
|
79
79
|
OTHER: :other # specify in remarks
|
@@ -129,6 +129,7 @@ module AIXM
|
|
129
129
|
|
130
130
|
# @!method frequencies
|
131
131
|
# @return [Array<AIXM::Component::Frequency>] frequencies used by this service
|
132
|
+
#
|
132
133
|
# @!method add_frequency(frequency)
|
133
134
|
# @param frequency [AIXM::Component::Frequency]
|
134
135
|
has_many :frequencies
|
@@ -137,6 +138,14 @@ module AIXM
|
|
137
138
|
# @return [AIXM::Feature::Unit] unit providing this service
|
138
139
|
belongs_to :unit
|
139
140
|
|
141
|
+
# @!method airport
|
142
|
+
# @return [AIXM::Feature::Airport] airport this service is provided at
|
143
|
+
belongs_to :airport
|
144
|
+
|
145
|
+
# @!method airspace
|
146
|
+
# @return [AIXM::Feature::Airspace] airspace this service is provided in
|
147
|
+
belongs_to :airspace
|
148
|
+
|
140
149
|
# @!method layer
|
141
150
|
# @return [AIXM::Component::Layer] airspace layer this service is provided within
|
142
151
|
belongs_to :layer
|
@@ -1,16 +1,15 @@
|
|
1
1
|
using AIXM::Refinements
|
2
2
|
|
3
3
|
module AIXM
|
4
|
-
|
4
|
+
class Component
|
5
5
|
|
6
6
|
# Surface of a runway, helipad etc
|
7
7
|
#
|
8
8
|
# ===Cheat Sheet in Pseudo Code:
|
9
|
-
# surface = AIXM.surface
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
# )
|
9
|
+
# surface = AIXM.surface
|
10
|
+
# surface.composition: COMPOSITIONS or nil
|
11
|
+
# surface.preparation: PREPARATIONS or nil
|
12
|
+
# surface.condition: CONDITIONS or nil
|
14
13
|
# surface.pcn = String or nil
|
15
14
|
# surface.siwl_weight = AIXM.w
|
16
15
|
# surface.siwl_tire_pressure = AIXM.p
|
@@ -20,9 +19,10 @@ module AIXM
|
|
20
19
|
# ===Constants:
|
21
20
|
# * +AIXM::PCN_RE+ - regular expression to match PCN notations
|
22
21
|
#
|
23
|
-
#
|
24
22
|
# @see https://gitlab.com/openflightmaps/ofmx/wikis/Airport#rwy-runway
|
25
|
-
|
23
|
+
# @see https://gitlab.com/openflightmaps/ofmx/wikis/Airport#tla-helipad-tlof
|
24
|
+
# @see https://gitlab.com/openflightmaps/ofmx/wikis/Airport#fto-fato
|
25
|
+
class Surface < Component
|
26
26
|
COMPOSITIONS = {
|
27
27
|
ASPH: :asphalt,
|
28
28
|
BITUM: :bitumen, # dug up, bound and rolled ground
|
@@ -38,7 +38,7 @@ module AIXM
|
|
38
38
|
SNOW: :snow,
|
39
39
|
WATER: :water,
|
40
40
|
OTHER: :other # specify in remarks
|
41
|
-
}
|
41
|
+
}.freeze
|
42
42
|
|
43
43
|
PREPARATIONS = {
|
44
44
|
AFSC: :aggregate_friction_seal_coat,
|
@@ -50,14 +50,14 @@ module AIXM
|
|
50
50
|
RFSC: :rubberized_friction_seal_coat,
|
51
51
|
ROLLED: :rolled,
|
52
52
|
OTHER: :other
|
53
|
-
}
|
53
|
+
}.freeze
|
54
54
|
|
55
55
|
CONDITIONS = {
|
56
56
|
GOOD: :good,
|
57
57
|
FAIR: :fair,
|
58
58
|
POOR: :poor,
|
59
59
|
OTHER: :other
|
60
|
-
}
|
60
|
+
}.freeze
|
61
61
|
|
62
62
|
# @return [Symbol, nil] composition of the surface (see {COMPOSITIONS})
|
63
63
|
attr_reader :composition
|
@@ -103,7 +103,7 @@ module AIXM
|
|
103
103
|
|
104
104
|
# @return [String, nil] pavement classification number (e.g. "59/F/A/W/T")
|
105
105
|
def pcn
|
106
|
-
@pcn.none? ? nil : @pcn.values.join("/")
|
106
|
+
@pcn.none? ? nil : @pcn.values.join("/".freeze)
|
107
107
|
end
|
108
108
|
|
109
109
|
def pcn=(value)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
using AIXM::Refinements
|
2
2
|
|
3
3
|
module AIXM
|
4
|
-
|
4
|
+
class Component
|
5
5
|
|
6
6
|
# Timetables define activity time windows.
|
7
7
|
#
|
@@ -18,7 +18,7 @@ module AIXM
|
|
18
18
|
# * +AIXM::H_RE+ - pattern matching working hour codes
|
19
19
|
#
|
20
20
|
# @see https://gitlab.com/openflightmaps/ofmx/wikis/Timetable#predefined-timetable
|
21
|
-
class Timetable
|
21
|
+
class Timetable < Component
|
22
22
|
CODES = {
|
23
23
|
H24: :continuous, # all day and all night
|
24
24
|
HJ: :sunrise_to_sunset, # all day
|
@@ -0,0 +1,105 @@
|
|
1
|
+
using AIXM::Refinements
|
2
|
+
|
3
|
+
module AIXM
|
4
|
+
class Component
|
5
|
+
|
6
|
+
# Visual approach slope indicator system
|
7
|
+
#
|
8
|
+
# ===Cheat Sheet in Pseudo Code:
|
9
|
+
# vasis = AIXM.vasis
|
10
|
+
# vasis.type = TYPES or nil
|
11
|
+
# vasis.position = POSITIONS or nil
|
12
|
+
# vasis.boxes = Integer or nil
|
13
|
+
# vasis.portable = true or false or nil (means: unknown, default)
|
14
|
+
# vasis.slope_angle = AIXM.a or nil
|
15
|
+
# vasis.meht = AIXM.d or nil
|
16
|
+
#
|
17
|
+
# @see https://gitlab.com/openflightmaps/ofmx/wikis/Airport#rdn-runway-direction
|
18
|
+
# @see https://gitlab.com/openflightmaps/ofmx/wikis/Airport#fdn-fato-direction
|
19
|
+
class VASIS < Component
|
20
|
+
TYPES = {
|
21
|
+
PAPI: :precision_api,
|
22
|
+
APAPI: :abbreviated_precision_api,
|
23
|
+
HAPI: :helicopter_api,
|
24
|
+
VASIS: :vasis,
|
25
|
+
AVASIS: :abbreviated_vasis,
|
26
|
+
TVASIS: :t_shaped_vasis,
|
27
|
+
ATVASIS: :abbreviated_t_shaped_vasis,
|
28
|
+
OTHER: :other # specify in remarks
|
29
|
+
}.freeze
|
30
|
+
|
31
|
+
POSITIONS = {
|
32
|
+
LEFT: :left,
|
33
|
+
RIGHT: :right,
|
34
|
+
BOTH: :left_and_right,
|
35
|
+
OTHER: :other # specify in remarks
|
36
|
+
}.freeze
|
37
|
+
|
38
|
+
# @return [Symbol, nil] type of VASIS (see {TYPES})
|
39
|
+
attr_reader :type
|
40
|
+
|
41
|
+
# @return [Symbol, nil] position relative to the runway (see {POSITIONS})
|
42
|
+
attr_reader :position
|
43
|
+
|
44
|
+
# @return [Integer, nil] number of boxes
|
45
|
+
attr_reader :boxes
|
46
|
+
|
47
|
+
# @return [Boolean, nil] whether the VASIS is portable
|
48
|
+
attr_reader :portable
|
49
|
+
|
50
|
+
# @return [AIXM::A, nil] appropriate approach slope angle
|
51
|
+
attr_reader :slope_angle
|
52
|
+
|
53
|
+
# @return [AIXM::Z, nil] minimum eye height over threshold (MEHT)
|
54
|
+
attr_reader :meht
|
55
|
+
|
56
|
+
# @return [String]
|
57
|
+
def inspect
|
58
|
+
%Q(#<#{self.class} type=#{type.inspect}>)
|
59
|
+
end
|
60
|
+
|
61
|
+
def type=(value)
|
62
|
+
@type = value.nil? ? nil : TYPES.lookup(value.to_s.to_sym, nil) || fail(ArgumentError, "invalid type")
|
63
|
+
end
|
64
|
+
|
65
|
+
def position=(value)
|
66
|
+
@position = value.nil? ? nil : POSITIONS.lookup(value.to_s.to_sym, nil) || fail(ArgumentError, "invalid position")
|
67
|
+
end
|
68
|
+
|
69
|
+
def boxes=(value)
|
70
|
+
fail(ArgumentError, "invalid boxes count") unless value.nil? || (value.is_a?(Integer) && value > 0)
|
71
|
+
@boxes = value
|
72
|
+
end
|
73
|
+
|
74
|
+
def portable=(value)
|
75
|
+
fail(ArgumentError, "invalid portable") unless [true, false, nil].include? value
|
76
|
+
@portable = value
|
77
|
+
end
|
78
|
+
|
79
|
+
def slope_angle=(value)
|
80
|
+
fail(ArgumentError, "invalid slope angle") unless value.nil? || (value.is_a?(AIXM::A) && value.deg <= 90)
|
81
|
+
@slope_angle = value
|
82
|
+
end
|
83
|
+
|
84
|
+
def meht=(value)
|
85
|
+
fail(ArgumentError, "invalid MEHT") unless value.nil? || (value.is_a?(AIXM::Z) && value.qfe?)
|
86
|
+
@meht = value
|
87
|
+
end
|
88
|
+
|
89
|
+
# @return [String] AIXM or OFMX markup
|
90
|
+
def to_xml
|
91
|
+
builder = Builder::XmlMarkup.new(indent: true)
|
92
|
+
builder.codeTypeVasis(TYPES.key(type).to_s) if type
|
93
|
+
builder.codePsnVasis(POSITIONS.key(position).to_s) if position
|
94
|
+
builder.noBoxVasis(boxes.to_s) if boxes
|
95
|
+
builder.codePortableVasis(portable ? 'Y' : 'N') unless portable.nil?
|
96
|
+
builder.valSlopeAngleGpVasis(slope_angle.to_f) if slope_angle
|
97
|
+
if meht
|
98
|
+
builder.valMeht(meht.alt.to_s)
|
99
|
+
builder.uomMeht('FT')
|
100
|
+
end
|
101
|
+
builder.target!
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
using AIXM::Refinements
|
2
2
|
|
3
3
|
module AIXM
|
4
|
-
|
4
|
+
class Component
|
5
5
|
|
6
6
|
# Vertical limit defines a 3D airspace vertically. It is often noted in
|
7
7
|
# AIP as follows:
|
@@ -25,7 +25,7 @@ module AIXM
|
|
25
25
|
# * +AIXM::UNLIMITED+ - no upper limit expressed as "FL 999"
|
26
26
|
#
|
27
27
|
# @see https://gitlab.com/openflightmaps/ofmx/wikis/Airspace#ase-airspace
|
28
|
-
class VerticalLimit
|
28
|
+
class VerticalLimit < Component
|
29
29
|
include AIXM::Association
|
30
30
|
|
31
31
|
# @api private
|
@@ -57,7 +57,7 @@ module AIXM
|
|
57
57
|
# @return [String]
|
58
58
|
def inspect
|
59
59
|
payload = %i(upper_z max_z lower_z min_z).map { %Q(#{_1}="#{send(_1)}") if send(_1) }.compact
|
60
|
-
%Q(#<#{self.class} #{payload.join(' ')}>)
|
60
|
+
%Q(#<#{self.class} #{payload.join(' '.freeze)}>)
|
61
61
|
end
|
62
62
|
|
63
63
|
def upper_z=(value)
|
data/lib/aixm/config.rb
CHANGED
@@ -48,6 +48,7 @@ module AIXM
|
|
48
48
|
#
|
49
49
|
# @!method aixm!
|
50
50
|
# @!method ofmx!
|
51
|
+
#
|
51
52
|
# @return [Symbol] schema key
|
52
53
|
SCHEMAS.each_key do |schema|
|
53
54
|
define_method("#{schema}!") { @@config.schema = schema }
|
@@ -63,6 +64,7 @@ module AIXM
|
|
63
64
|
#
|
64
65
|
# @!method aixm?
|
65
66
|
# @!method ofmx?
|
67
|
+
#
|
66
68
|
# @return [Boolean]
|
67
69
|
SCHEMAS.each_key do |schema|
|
68
70
|
define_method("#{schema}?") { @@config.schema == schema }
|
data/lib/aixm/d.rb
CHANGED
@@ -2,7 +2,7 @@ using AIXM::Refinements
|
|
2
2
|
|
3
3
|
module AIXM
|
4
4
|
|
5
|
-
#
|
5
|
+
# Dimension, distance or length
|
6
6
|
#
|
7
7
|
# @example
|
8
8
|
# AIXM.d(123, :m)
|
@@ -18,17 +18,17 @@ module AIXM
|
|
18
18
|
}.freeze
|
19
19
|
|
20
20
|
# @!method zero?
|
21
|
-
# @return [Boolean] whether
|
22
|
-
def_delegator :@
|
21
|
+
# @return [Boolean] whether dimension is zero
|
22
|
+
def_delegator :@dim, :zero?
|
23
23
|
|
24
|
-
# @return [Float]
|
25
|
-
attr_reader :
|
24
|
+
# @return [Float] dimension
|
25
|
+
attr_reader :dim
|
26
26
|
|
27
27
|
# @return [Symbol] unit (see {UNITS})
|
28
28
|
attr_reader :unit
|
29
29
|
|
30
|
-
def initialize(
|
31
|
-
self.
|
30
|
+
def initialize(dim, unit)
|
31
|
+
self.dim, self.unit = dim, unit
|
32
32
|
end
|
33
33
|
|
34
34
|
# @return [String]
|
@@ -36,14 +36,14 @@ module AIXM
|
|
36
36
|
%Q(#<#{self.class} #{to_s}>)
|
37
37
|
end
|
38
38
|
|
39
|
-
# @return [String] human readable representation (e.g. "123 m")
|
39
|
+
# @return [String] human readable representation (e.g. "123.0 m")
|
40
40
|
def to_s
|
41
|
-
[
|
41
|
+
[dim, unit].join(' '.freeze)
|
42
42
|
end
|
43
43
|
|
44
|
-
def
|
45
|
-
fail(ArgumentError, "invalid
|
46
|
-
@
|
44
|
+
def dim=(value)
|
45
|
+
fail(ArgumentError, "invalid dim") unless value.is_a?(Numeric) && value >= 0
|
46
|
+
@dim = value.to_f
|
47
47
|
end
|
48
48
|
|
49
49
|
def unit=(value)
|
@@ -56,18 +56,19 @@ module AIXM
|
|
56
56
|
# @!method to_km
|
57
57
|
# @!method to_m
|
58
58
|
# @!method to_nm
|
59
|
-
#
|
59
|
+
#
|
60
|
+
# @return [AIXM::D] convert dimension
|
60
61
|
UNITS.each_key do |target_unit|
|
61
62
|
define_method "to_#{target_unit}" do
|
62
63
|
return self if unit == target_unit
|
63
|
-
self.class.new((
|
64
|
+
self.class.new((dim * UNITS[unit][target_unit]).round(8), target_unit)
|
64
65
|
end
|
65
66
|
end
|
66
67
|
|
67
68
|
# @see Object#<=>
|
68
69
|
# @return [Integer]
|
69
70
|
def <=>(other)
|
70
|
-
|
71
|
+
dim <=> other.send(:"to_#{unit}").dim
|
71
72
|
end
|
72
73
|
|
73
74
|
# @see Object#==
|