aixm 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +43 -13
  4. data/README.md +31 -20
  5. data/lib/aixm/a.rb +89 -71
  6. data/lib/aixm/association.rb +37 -27
  7. data/lib/aixm/classes.rb +5 -2
  8. data/lib/aixm/{feature → component}/address.rb +12 -9
  9. data/lib/aixm/component/approach_lighting.rb +136 -0
  10. data/lib/aixm/component/fato.rb +58 -42
  11. data/lib/aixm/component/frequency.rb +2 -2
  12. data/lib/aixm/component/geometry/arc.rb +1 -1
  13. data/lib/aixm/component/geometry/border.rb +1 -1
  14. data/lib/aixm/component/geometry/circle.rb +3 -3
  15. data/lib/aixm/component/geometry/point.rb +1 -1
  16. data/lib/aixm/component/geometry/rhumb_line.rb +1 -1
  17. data/lib/aixm/component/geometry.rb +3 -2
  18. data/lib/aixm/component/helipad.rb +26 -36
  19. data/lib/aixm/component/layer.rb +5 -3
  20. data/lib/aixm/component/lighting.rb +5 -5
  21. data/lib/aixm/component/runway.rb +81 -52
  22. data/lib/aixm/component/service.rb +12 -3
  23. data/lib/aixm/component/surface.rb +12 -12
  24. data/lib/aixm/component/timetable.rb +2 -2
  25. data/lib/aixm/component/vasis.rb +105 -0
  26. data/lib/aixm/component/vertical_limit.rb +3 -3
  27. data/lib/aixm/component.rb +10 -0
  28. data/lib/aixm/config.rb +2 -0
  29. data/lib/aixm/d.rb +16 -15
  30. data/lib/aixm/document.rb +10 -1
  31. data/lib/aixm/f.rb +1 -1
  32. data/lib/aixm/feature/airport.rb +34 -10
  33. data/lib/aixm/feature/airspace.rb +3 -0
  34. data/lib/aixm/feature/navigational_aid/dme.rb +29 -10
  35. data/lib/aixm/feature/navigational_aid/marker.rb +2 -2
  36. data/lib/aixm/feature/navigational_aid/tacan.rb +3 -2
  37. data/lib/aixm/feature/navigational_aid/vor.rb +32 -13
  38. data/lib/aixm/feature/navigational_aid.rb +1 -1
  39. data/lib/aixm/feature/obstacle.rb +6 -6
  40. data/lib/aixm/feature/obstacle_group.rb +6 -2
  41. data/lib/aixm/feature/organisation.rb +1 -0
  42. data/lib/aixm/feature/unit.rb +2 -1
  43. data/lib/aixm/feature.rb +3 -0
  44. data/lib/aixm/memoize.rb +27 -11
  45. data/lib/aixm/p.rb +3 -2
  46. data/lib/aixm/payload_hash.rb +1 -1
  47. data/lib/aixm/r.rb +62 -0
  48. data/lib/aixm/refinements.rb +4 -4
  49. data/lib/aixm/version.rb +1 -1
  50. data/lib/aixm/w.rb +2 -1
  51. data/lib/aixm/xy.rb +1 -1
  52. data/lib/aixm/z.rb +5 -4
  53. data/lib/aixm.rb +10 -5
  54. data/schemas/ofmx/0.1/OFMX-DataTypes.xsd +6 -0
  55. data/schemas/ofmx/0.1/OFMX-Snapshot.xsd +5 -0
  56. data.tar.gz.sig +0 -0
  57. metadata +8 -4
  58. metadata.gz.sig +0 -0
@@ -1,7 +1,7 @@
1
1
  using AIXM::Refinements
2
2
 
3
3
  module AIXM
4
- module Component
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.length = AIXM.d or nil # must use same unit as width
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[precision=2] # preset based on the runway name
25
- # runway.forth.geographic_orientation = AIXM.a[precision=3] or nil
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.geographic_orientation = 165
39
+ # runway.forth.geographic_bearing = 165
37
40
  # runway.back.name.to_s = '34R'
38
- # runway.back.geographic_orientation = 345
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.geographic_orientation = 165
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::D, nil] length
81
- attr_reader :length
92
+ # @return [AIXM::R, nil] dimensions
93
+ attr_reader :dimensions
82
94
 
83
- # @return [AIXM::D, nil] width
84
- attr_reader :width
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
- @surface = AIXM.surface
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 length=(value)
116
- @length = if value
117
- fail(ArgumentError, "invalid length") unless value.is_a?(AIXM::D) && value.dist > 0
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 width=(value)
124
- @width = if value
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
- rwy.valLen(length.dist.trim) if length
155
- rwy.valWid(width.dist.trim) if width
156
- rwy.uomDimRwy(length.unit.to_s.upcase) if length
157
- rwy.uomDimRwy(width.unit.to_s.upcase) if width && !length
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] geographic orientation (true bearing) in degrees
201
- attr_reader :geographic_orientation
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 geographic_orientation=(value)
235
- return @geographic_orientation = nil if value.nil?
236
- fail(ArgumentError, "invalid geographic orientation") unless value.is_a? AIXM::A
237
- @geographic_orientation = value
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.dist > 0
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 orientation (magnetic bearing) in degrees
273
- def magnetic_orientation
274
- if geographic_orientation && runway.airport.declination
275
- geographic_orientation - runway.airport.declination
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(geographic_orientation) if geographic_orientation
297
- rdn.valMagBrg(magnetic_orientation) if magnetic_orientation
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.dist.trim)
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
- module Component
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: :vhf_direction_finding_service,
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
- module Component
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
- # composition: COMPOSITIONS or nil
11
- # preparation: PREPARATIONS or nil
12
- # condition: CONDITIONS or nil
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
- class Surface
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
- module Component
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
- module Component
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)
@@ -0,0 +1,10 @@
1
+ module AIXM
2
+
3
+ # @abstract
4
+ class Component
5
+
6
+ # @return [Object] freely usable e.g. to find_by foreign keys
7
+ attr_accessor :meta
8
+
9
+ end
10
+ end
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
- # Distance or length
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 distance is zero
22
- def_delegator :@dist, :zero?
21
+ # @return [Boolean] whether dimension is zero
22
+ def_delegator :@dim, :zero?
23
23
 
24
- # @return [Float] distance
25
- attr_reader :dist
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(dist, unit)
31
- self.dist, self.unit = dist, unit
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
- [dist, unit].join(' ')
41
+ [dim, unit].join(' '.freeze)
42
42
  end
43
43
 
44
- def dist=(value)
45
- fail(ArgumentError, "invalid dist") unless value.is_a?(Numeric) && value >= 0
46
- @dist = value.to_f
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
- # @return [AIXM::D] convert distance
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((dist * UNITS[unit][target_unit]).round(8), target_unit)
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
- dist <=> other.send(:"to_#{unit}").dist
71
+ dim <=> other.send(:"to_#{unit}").dim
71
72
  end
72
73
 
73
74
  # @see Object#==