aixm 0.3.8 → 0.3.10

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.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +1 -0
  3. data.tar.gz.sig +0 -0
  4. data/CHANGELOG.md +33 -3
  5. data/README.md +166 -56
  6. data/exe/ckmid +14 -0
  7. data/exe/mkmid +14 -0
  8. data/lib/aixm.rb +16 -6
  9. data/lib/aixm/association.rb +369 -0
  10. data/lib/aixm/classes.rb +43 -0
  11. data/lib/aixm/component/fato.rb +45 -53
  12. data/lib/aixm/component/frequency.rb +11 -12
  13. data/lib/aixm/component/geometry.rb +36 -38
  14. data/lib/aixm/component/geometry/arc.rb +2 -2
  15. data/lib/aixm/component/geometry/border.rb +6 -3
  16. data/lib/aixm/component/geometry/circle.rb +8 -2
  17. data/lib/aixm/component/geometry/point.rb +8 -2
  18. data/lib/aixm/component/helipad.rb +30 -38
  19. data/lib/aixm/component/layer.rb +28 -19
  20. data/lib/aixm/component/lighting.rb +12 -13
  21. data/lib/aixm/component/runway.rb +44 -48
  22. data/lib/aixm/{feature → component}/service.rb +37 -36
  23. data/lib/aixm/component/surface.rb +3 -3
  24. data/lib/aixm/component/timetable.rb +2 -2
  25. data/lib/aixm/component/{vertical_limits.rb → vertical_limit.rb} +12 -6
  26. data/lib/aixm/config.rb +2 -1
  27. data/lib/aixm/document.rb +27 -50
  28. data/lib/aixm/executables.rb +85 -0
  29. data/lib/aixm/feature.rb +13 -3
  30. data/lib/aixm/feature/address.rb +12 -13
  31. data/lib/aixm/feature/airport.rb +103 -128
  32. data/lib/aixm/feature/airspace.rb +44 -17
  33. data/lib/aixm/feature/navigational_aid.rb +7 -9
  34. data/lib/aixm/feature/navigational_aid/designated_point.rb +13 -15
  35. data/lib/aixm/feature/navigational_aid/dme.rb +11 -12
  36. data/lib/aixm/feature/navigational_aid/marker.rb +7 -3
  37. data/lib/aixm/feature/navigational_aid/ndb.rb +7 -3
  38. data/lib/aixm/feature/navigational_aid/tacan.rb +7 -3
  39. data/lib/aixm/feature/navigational_aid/vor.rb +23 -15
  40. data/lib/aixm/feature/obstacle.rb +29 -43
  41. data/lib/aixm/feature/obstacle_group.rb +37 -34
  42. data/lib/aixm/feature/organisation.rb +21 -5
  43. data/lib/aixm/feature/unit.rb +36 -46
  44. data/lib/aixm/memoize.rb +89 -0
  45. data/lib/aixm/object.rb +9 -0
  46. data/lib/aixm/payload_hash.rb +114 -0
  47. data/lib/aixm/refinements.rb +29 -76
  48. data/lib/aixm/shortcuts.rb +5 -42
  49. data/lib/aixm/version.rb +1 -1
  50. data/lib/aixm/xy.rb +1 -1
  51. data/schemas/ofmx/0/OFMX-Features.xsd +152 -20
  52. data/schemas/ofmx/0/OFMX-Snapshot.xsd +0 -5
  53. metadata +107 -156
  54. metadata.gz.sig +2 -0
  55. data/.github/workflows/test.yml +0 -26
  56. data/.gitignore +0 -6
  57. data/.ruby-version +0 -1
  58. data/.yardopts +0 -3
  59. data/Guardfile +0 -8
  60. data/aixm.gemspec +0 -35
  61. data/gems.rb +0 -3
  62. data/lib/aixm/component.rb +0 -6
  63. data/rakefile.rb +0 -36
  64. data/spec/factory.rb +0 -559
  65. data/spec/lib/aixm/a_spec.rb +0 -203
  66. data/spec/lib/aixm/component/fato_spec.rb +0 -267
  67. data/spec/lib/aixm/component/frequency_spec.rb +0 -74
  68. data/spec/lib/aixm/component/geometry/arc_spec.rb +0 -73
  69. data/spec/lib/aixm/component/geometry/border_spec.rb +0 -38
  70. data/spec/lib/aixm/component/geometry/circle_spec.rb +0 -68
  71. data/spec/lib/aixm/component/geometry/point_spec.rb +0 -37
  72. data/spec/lib/aixm/component/geometry_spec.rb +0 -316
  73. data/spec/lib/aixm/component/helipad_spec.rb +0 -193
  74. data/spec/lib/aixm/component/layer_spec.rb +0 -135
  75. data/spec/lib/aixm/component/lighting_spec.rb +0 -94
  76. data/spec/lib/aixm/component/runway_spec.rb +0 -479
  77. data/spec/lib/aixm/component/surface_spec.rb +0 -124
  78. data/spec/lib/aixm/component/timetable_spec.rb +0 -47
  79. data/spec/lib/aixm/component/vertical_limits_spec.rb +0 -94
  80. data/spec/lib/aixm/config_spec.rb +0 -41
  81. data/spec/lib/aixm/d_spec.rb +0 -150
  82. data/spec/lib/aixm/document_spec.rb +0 -1884
  83. data/spec/lib/aixm/errors_spec.rb +0 -14
  84. data/spec/lib/aixm/f_spec.rb +0 -85
  85. data/spec/lib/aixm/feature/address_spec.rb +0 -60
  86. data/spec/lib/aixm/feature/airport_spec.rb +0 -776
  87. data/spec/lib/aixm/feature/airspace_spec.rb +0 -394
  88. data/spec/lib/aixm/feature/navigational_aid/designated_point_spec.rb +0 -103
  89. data/spec/lib/aixm/feature/navigational_aid/dme_spec.rb +0 -98
  90. data/spec/lib/aixm/feature/navigational_aid/marker_spec.rb +0 -85
  91. data/spec/lib/aixm/feature/navigational_aid/ndb_spec.rb +0 -95
  92. data/spec/lib/aixm/feature/navigational_aid/tacan_spec.rb +0 -94
  93. data/spec/lib/aixm/feature/navigational_aid/vor_spec.rb +0 -251
  94. data/spec/lib/aixm/feature/navigational_aid_spec.rb +0 -52
  95. data/spec/lib/aixm/feature/obstacle_group_spec.rb +0 -330
  96. data/spec/lib/aixm/feature/obstacle_spec.rb +0 -284
  97. data/spec/lib/aixm/feature/organisation_spec.rb +0 -83
  98. data/spec/lib/aixm/feature/service_spec.rb +0 -59
  99. data/spec/lib/aixm/feature/unit_spec.rb +0 -238
  100. data/spec/lib/aixm/feature_spec.rb +0 -38
  101. data/spec/lib/aixm/p_spec.rb +0 -189
  102. data/spec/lib/aixm/refinements_spec.rb +0 -430
  103. data/spec/lib/aixm/version_spec.rb +0 -7
  104. data/spec/lib/aixm/w_spec.rb +0 -150
  105. data/spec/lib/aixm/xy_spec.rb +0 -180
  106. data/spec/lib/aixm/z_spec.rb +0 -94
  107. data/spec/macros/marking.rb +0 -12
  108. data/spec/macros/organisation.rb +0 -11
  109. data/spec/macros/remarks.rb +0 -12
  110. data/spec/macros/timetable.rb +0 -11
  111. data/spec/macros/xy.rb +0 -11
  112. data/spec/macros/z_qnh.rb +0 -11
  113. data/spec/sounds/failure.mp3 +0 -0
  114. data/spec/sounds/success.mp3 +0 -0
  115. data/spec/spec_helper.rb +0 -62
@@ -1,7 +1,7 @@
1
1
  using AIXM::Refinements
2
2
 
3
3
  module AIXM
4
- class Component
4
+ module Component
5
5
 
6
6
  # Frequencies used by a service.
7
7
  #
@@ -20,8 +20,11 @@ module AIXM
20
20
  # frequency.timetable = AIXM.timetable or nil
21
21
  # frequency.remarks = String or nil
22
22
  #
23
- # @see https://github.com/openflightmaps/ofmx/wiki/Organisation#fqy-frequency
23
+ # @see https://gitlab.com/openflightmaps/ofmx/wikis/Organisation#fqy-frequency
24
24
  class Frequency
25
+ include AIXM::Association
26
+ include AIXM::Memoize
27
+
25
28
  TYPES = {
26
29
  STD: :standard,
27
30
  ALT: :alternative,
@@ -32,8 +35,9 @@ module AIXM
32
35
  OTHER: :other # specify in remarks
33
36
  }.freeze
34
37
 
35
- # @return [AIXM::Feature::Service] service the frequency belongs to
36
- attr_reader :service
38
+ # @!method service
39
+ # @return [AIXM::Component::Service] service the frequency belongs to
40
+ belongs_to :service
37
41
 
38
42
  # @return [AIXM::F] frequency for transmission (outgoing)
39
43
  attr_reader :transmission_f
@@ -68,12 +72,6 @@ module AIXM
68
72
  %Q(#<#{self.class} transmission_f=#{transmission_f.inspect} callsigns=#{callsigns.inspect}>)
69
73
  end
70
74
 
71
- def service=(value)
72
- fail(ArgumentError, "invalid service") unless value.is_a? AIXM::Feature::Service
73
- @service = value
74
- end
75
- private :service=
76
-
77
75
  def transmission_f=(value)
78
76
  fail(ArgumentError, "invalid transmission_f") unless value.is_a? AIXM::F
79
77
  @transmission_f = value
@@ -81,7 +79,7 @@ module AIXM
81
79
 
82
80
  def callsigns=(value)
83
81
  fail(ArgumentError, "invalid callsigns") unless value.is_a?(Hash)
84
- @callsigns = value.transform_keys { |k| k.to_sym.downcase }.transform_values { |v| v.to_s.uptrans }
82
+ @callsigns = value.transform_keys { _1.to_sym.downcase }.transform_values { _1.to_s.uptrans }
85
83
  end
86
84
 
87
85
  def reception_f=(value)
@@ -108,8 +106,9 @@ module AIXM
108
106
  builder.FqyUid do |fqy_uid|
109
107
  fqy_uid << service.to_uid.indent(2)
110
108
  fqy_uid.valFreqTrans(transmission_f.freq)
111
- end.insert_payload_hash(region: AIXM.config.mid_region)
109
+ end
112
110
  end
111
+ memoize :to_uid
113
112
 
114
113
  # @return [String] AIXM or OFMX markup
115
114
  def to_xml
@@ -1,11 +1,9 @@
1
1
  using AIXM::Refinements
2
2
 
3
3
  module AIXM
4
- class Component
4
+ module Component
5
5
 
6
- # Geometries define a 3D airspace horizontally. It's either exactly one
7
- # circle or at least three points, arcs and borders (the last of which
8
- # has to be a point with the same coordinates as the first).
6
+ # Geometries define a 3D airspace horizontally.
9
7
  #
10
8
  # For a geometry to be valid, it must be comprised of either:
11
9
  # * exactly one point
@@ -15,7 +13,7 @@ module AIXM
15
13
  #
16
14
  # ===Cheat Sheet in Pseudo Code:
17
15
  # geometry = AIXM.geometry
18
- # geometry << AIXM.point or AIXM.arc or AIXM.border or AIXM.circle
16
+ # geometry.add_segment(AIXM.point or AIXM.arc or AIXM.border or AIXM.circle)
19
17
  #
20
18
  # @example Built by passing elements to the initializer
21
19
  # geometry = AIXM.geometry(
@@ -23,26 +21,33 @@ module AIXM
23
21
  # AIXM.point(...)
24
22
  # )
25
23
  #
26
- # @example Built by adding elements
24
+ # @example Built by adding segments
27
25
  # geometry = AIXM.geometry
28
- # geometry << AIXM.point(...)
29
- # geometry.concat [AIXM.point(...), AIXM.point(...), ...]
26
+ # geometry.add_segment(AIXM.point(...))
30
27
  #
31
- # @see https://github.com/openflightmaps/ofmx/wiki/Airspace#avx-border-vertex
28
+ # @see https://gitlab.com/openflightmaps/ofmx/wikis/Airspace#avx-border-vertex
32
29
  class Geometry
33
- include Enumerable
34
- extend Forwardable
30
+ include AIXM::Association
35
31
 
36
- # @!method each
37
- # @return [Enumerator] see Array#each
38
- # @!method <<
39
- # @return [Array] see Array#<<
40
- # @!method concat
41
- # @return [Array] see Array#concat
42
- def_delegators :@result_array, :each, :<<, :concat
32
+ # @!method segments
33
+ # @return [Array<AIXM::Component::Geometry::Point,
34
+ # AIXM::Component::Geometry::Arc,
35
+ # AIXM::Component::Geometry::Border,
36
+ # AIXM::Component::Geometry::Circle>] points, arcs, borders or circle
37
+ # @!method add_segment(segment)
38
+ # @param segment [AIXM::Component::Geometry::Point,
39
+ # AIXM::Component::Geometry::Arc,
40
+ # AIXM::Component::Geometry::Border,
41
+ # AIXM::Component::Geometry::Circle]
42
+ # @return [self]
43
+ has_many :segments, accept: %i(point arc border circle)
44
+
45
+ # @!method airspace
46
+ # @return [AIXM::Feature::Airspace] airspace the geometry defines
47
+ belongs_to :airspace
43
48
 
44
49
  def initialize(*segments)
45
- @result_array = segments
50
+ segments.each { add_segment(_1) }
46
51
  end
47
52
 
48
53
  # @return [String]
@@ -50,14 +55,6 @@ module AIXM
50
55
  %Q(#<#{self.class} segments=#{segments.count.inspect}>)
51
56
  end
52
57
 
53
- # @return [Array<AIXM::Component::Geometry::Point,
54
- # AIXM::Component::Geometry::Arc,
55
- # AIXM::Component::Geometry::Border,
56
- # AIXM::Component::Geometry::Circle>] points, arcs, borders or circle
57
- def segments
58
- @result_array
59
- end
60
-
61
58
  # @return [Boolean] whether the geometry is closed
62
59
  def closed?
63
60
  point? || circle? || polygon?
@@ -66,26 +63,27 @@ module AIXM
66
63
  # @return [String] AIXM or OFMX markup
67
64
  def to_xml
68
65
  fail(GeometryError.new("geometry is not closed", self)) unless closed?
69
- @result_array.map { |h| h.to_xml }.join
66
+ segments.map { _1.to_xml }.join
70
67
  end
71
68
 
72
- private
73
-
69
+ # @return [Boolean] Single point geometry?
74
70
  def point?
75
- @result_array.size == 1 &&
76
- @result_array.first.is_a?(AIXM::Component::Geometry::Point)
71
+ segments.size == 1 &&
72
+ segments.first.is_a?(AIXM::Component::Geometry::Point)
77
73
  end
78
74
 
75
+ # @return [Boolean] Circle shaped geometry?
79
76
  def circle?
80
- @result_array.size == 1 &&
81
- @result_array.first.is_a?(AIXM::Component::Geometry::Circle)
77
+ segments.size == 1 &&
78
+ segments.first.is_a?(AIXM::Component::Geometry::Circle)
82
79
  end
83
80
 
81
+ # @return [Boolean] Polygon shaped geometry?
84
82
  def polygon?
85
- @result_array.size >= 3 &&
86
- !@result_array.any? { |h| h.is_a?(AIXM::Component::Geometry::Circle) } &&
87
- @result_array.last.is_a?(AIXM::Component::Geometry::Point) &&
88
- @result_array.first.xy == @result_array.last.xy
83
+ segments.size >= 3 &&
84
+ !segments.any? { _1.is_a?(AIXM::Component::Geometry::Circle) } &&
85
+ segments.last.is_a?(AIXM::Component::Geometry::Point) &&
86
+ segments.first.xy == segments.last.xy
89
87
  end
90
88
  end
91
89
 
@@ -1,7 +1,7 @@
1
1
  using AIXM::Refinements
2
2
 
3
3
  module AIXM
4
- class Component
4
+ module Component
5
5
  class Geometry
6
6
 
7
7
  # Arcs are clockwise or counter clockwise circle segments around a
@@ -14,7 +14,7 @@ module AIXM
14
14
  # clockwise: true or false
15
15
  # )
16
16
  #
17
- # @see https://github.com/openflightmaps/ofmx/wiki/Airspace#arc
17
+ # @see https://gitlab.com/openflightmaps/ofmx/wikis/Airspace#arc
18
18
  class Arc < Point
19
19
  # @return [AIXM::XY] center point
20
20
  attr_reader :center_xy
@@ -1,7 +1,7 @@
1
1
  using AIXM::Refinements
2
2
 
3
3
  module AIXM
4
- class Component
4
+ module Component
5
5
  class Geometry
6
6
 
7
7
  # Borders are following natural or artifical border lines referenced by
@@ -13,8 +13,10 @@ module AIXM
13
13
  # name: String
14
14
  # )
15
15
  #
16
- # @see https://github.com/openflightmaps/ofmx/wiki/Airspace#frontier
16
+ # @see https://gitlab.com/openflightmaps/ofmx/wikis/Airspace#frontier
17
17
  class Border < Point
18
+ include AIXM::Memoize
19
+
18
20
  # @return [String] name of the border
19
21
  attr_reader :name
20
22
 
@@ -38,8 +40,9 @@ module AIXM
38
40
  builder = Builder::XmlMarkup.new(indent: 2)
39
41
  builder.tag!(as) do |tag|
40
42
  tag.txtName(name.to_s)
41
- end.insert_payload_hash(region: AIXM.config.mid_region)
43
+ end
42
44
  end
45
+ memoize :to_uid
43
46
 
44
47
  # @return [String] AIXM or OFMX markup
45
48
  def to_xml
@@ -1,7 +1,7 @@
1
1
  using AIXM::Refinements
2
2
 
3
3
  module AIXM
4
- class Component
4
+ module Component
5
5
  class Geometry
6
6
 
7
7
  # Circles are defined by a {#center_xy} and a {#radius}.
@@ -12,8 +12,14 @@ module AIXM
12
12
  # radius: AIXM.d
13
13
  # )
14
14
  #
15
- # @see https://github.com/openflightmaps/ofmx/wiki/Airspace#circle
15
+ # @see https://gitlab.com/openflightmaps/ofmx/wikis/Airspace#circle
16
16
  class Circle
17
+ include AIXM::Association
18
+
19
+ # @!method geometry
20
+ # @return [AIXM::Component::Geometry] geometry the arc belongs to
21
+ belongs_to :geometry, as: :segment
22
+
17
23
  # @return [AIXM::XY] center point
18
24
  attr_reader :center_xy
19
25
 
@@ -1,7 +1,7 @@
1
1
  using AIXM::Refinements
2
2
 
3
3
  module AIXM
4
- class Component
4
+ module Component
5
5
  class Geometry
6
6
 
7
7
  # Points are defined by {#xy} coordinates.
@@ -11,8 +11,14 @@ module AIXM
11
11
  # xy: AIXM.xy
12
12
  # )
13
13
  #
14
- # @see https://github.com/openflightmaps/ofmx/wiki/Airspace#point
14
+ # @see https://gitlab.com/openflightmaps/ofmx/wikis/Airspace#point
15
15
  class Point
16
+ include AIXM::Association
17
+
18
+ # @!method geometry
19
+ # @return [AIXM::Component::Geometry] geometry the arc belongs to
20
+ belongs_to :geometry, as: :segment
21
+
16
22
  # @return [AIXM::XY] (starting) point
17
23
  attr_reader :xy
18
24
 
@@ -1,7 +1,7 @@
1
1
  using AIXM::Refinements
2
2
 
3
3
  module AIXM
4
- class Component
4
+ module Component
5
5
 
6
6
  # Helipads are TLOF (touch-down and lift-off areas) for vertical take-off
7
7
  # aircraft such as helicopters.
@@ -21,8 +21,11 @@ module AIXM
21
21
  # helipad.status = STATUSES or nil
22
22
  # helipad.remarks = String or nil
23
23
  #
24
- # @see https://github.com/openflightmaps/ofmx/wiki/Airport#tla-helipad-tlof
24
+ # @see https://gitlab.com/openflightmaps/ofmx/wikis/Airport#tla-helipad-tlof
25
25
  class Helipad
26
+ include AIXM::Association
27
+ include AIXM::Memoize
28
+
26
29
  HELICOPTER_CLASSES = {
27
30
  '1': :'1',
28
31
  '2': :'2',
@@ -39,8 +42,28 @@ module AIXM
39
42
  OTHER: :other # specify in remarks
40
43
  }.freeze
41
44
 
42
- # @return [AIXM::Feature::Airport] airport this helipad belongs to
43
- attr_reader :airport
45
+ # @!method fato
46
+ # @return [AIXM::Component::FATO, nil] FATO the helipad is situated on
47
+ # @!method fato=(fato)
48
+ # @param fato [AIXM::Component::FATO, nil]
49
+ has_one :fato, allow_nil: true
50
+
51
+ # @!method surface
52
+ # @return [AIXM::Component::Surface] surface of the helipad
53
+ # @!method surface=(surface)
54
+ # @param surface [AIXM::Component::Surface]
55
+ has_one :surface
56
+
57
+ # @!method lightings
58
+ # @return [Array<AIXM::Component::Lighting>] installed lighting systems
59
+ # @!method add_lighting(lighting)
60
+ # @param lighting [AIXM::Component::Lighting]
61
+ # @return [self]
62
+ has_many :lightings, as: :lightable
63
+
64
+ # @!method airport
65
+ # @return [AIXM::Feature::Airport] airport this helipad belongs to
66
+ belongs_to :airport
44
67
 
45
68
  # @return [String] full name (e.g. "H1")
46
69
  attr_reader :name
@@ -57,15 +80,9 @@ module AIXM
57
80
  # @return [AIXM::D, nil] width
58
81
  attr_reader :width
59
82
 
60
- # @return [AIXM::Component::Surface] surface of the helipad
61
- attr_reader :surface
62
-
63
83
  # @return [String, nil] markings
64
84
  attr_reader :marking
65
85
 
66
- # @return [AIXM::Component::FATO, nil] FATO the helipad is situated on
67
- attr_reader :fato
68
-
69
86
  # @return [Integer, Symbol, nil] suitable helicopter class
70
87
  attr_reader :helicopter_class
71
88
 
@@ -75,13 +92,9 @@ module AIXM
75
92
  # @return [String, nil] free text remarks
76
93
  attr_reader :remarks
77
94
 
78
- # @return [Array<AIXM::Component::Lighting>] installed lighting systems
79
- attr_reader :lightings
80
-
81
95
  def initialize(name:, xy:)
82
96
  self.name, self.xy = name, xy
83
- @surface = AIXM.surface
84
- @lightings = []
97
+ self.surface = AIXM.surface
85
98
  end
86
99
 
87
100
  # @return [String]
@@ -89,12 +102,6 @@ module AIXM
89
102
  %Q(#<#{self.class} airport=#{airport&.id.inspect} name=#{name.inspect}>)
90
103
  end
91
104
 
92
- def airport=(value)
93
- fail(ArgumentError, "invalid airport") unless value.is_a? AIXM::Feature::Airport
94
- @airport = value
95
- end
96
- private :airport=
97
-
98
105
  def name=(value)
99
106
  fail(ArgumentError, "invalid name") unless value.is_a? String
100
107
  @name = value.uptrans
@@ -130,11 +137,6 @@ module AIXM
130
137
  @marking = value&.to_s
131
138
  end
132
139
 
133
- def fato=(value)
134
- fail(ArgumentError, "invalid FATO") unless value.nil? || value.is_a?(AIXM::Component::FATO)
135
- @fato = value
136
- end
137
-
138
140
  def helicopter_class=(value)
139
141
  @helicopter_class = value.nil? ? nil : (HELICOPTER_CLASSES.lookup(value.to_s.to_sym, nil) || fail(ArgumentError, "invalid helicopter class"))
140
142
  end
@@ -147,25 +149,15 @@ module AIXM
147
149
  @remarks = value&.to_s
148
150
  end
149
151
 
150
- # Add a lighting system to the runway direction.
151
- #
152
- # @param lighting [AIXM::Component::Lighting] lighting instance
153
- # @return [self]
154
- def add_lighting(lighting)
155
- fail(ArgumentError, "invalid lighting") unless lighting.is_a? AIXM::Component::Lighting
156
- lighting.send(:lightable=, self)
157
- @lightings << lighting
158
- self
159
- end
160
-
161
152
  # @return [String] UID markup
162
153
  def to_uid
163
154
  builder = Builder::XmlMarkup.new(indent: 2)
164
155
  builder.TlaUid do |tla_uid|
165
156
  tla_uid << airport.to_uid.indent(2)
166
157
  tla_uid.txtDesig(name)
167
- end.insert_payload_hash(region: AIXM.config.mid_region)
158
+ end
168
159
  end
160
+ memoize :to_uid
169
161
 
170
162
  # @return [String] AIXM or OFMX markup
171
163
  def to_xml
@@ -1,24 +1,27 @@
1
1
  using AIXM::Refinements
2
2
 
3
3
  module AIXM
4
- class Component
4
+ module Component
5
5
 
6
6
  # Each airspace has one or more layers with optional airspace class and
7
- # mandatory vertical limits.
7
+ # mandatory vertical limit.
8
8
  #
9
9
  # ===Cheat Sheet in Pseudo Code:
10
10
  # layer = AIXM.layer(
11
11
  # class: String or nil
12
12
  # location_indicator: String or nil
13
- # vertical_limits: AIXM.vertical_limits
13
+ # vertical_limit: AIXM.vertical_limit
14
14
  # )
15
15
  # layer.activity = String or nil
16
16
  # layer.timetable = AIXM.timetable or nil
17
17
  # layer.selective = true or false (default)
18
18
  # layer.remarks = String or nil
19
+ # airspace.add_service(AIXM.service)
19
20
  #
20
- # @see https://github.com/openflightmaps/ofmx/wiki/Airspace
21
+ # @see https://gitlab.com/openflightmaps/ofmx/wikis/Airspace
21
22
  class Layer
23
+ include AIXM::Association
24
+
22
25
  CLASSES = (:A..:G).freeze
23
26
 
24
27
  ACTIVITIES = {
@@ -85,12 +88,25 @@ module AIXM
85
88
  OTHER: :other
86
89
  }.freeze
87
90
 
91
+ # @!method vertical_limit
92
+ # @return [AIXM::Component::VerticalLimit] vertical limit of this layer
93
+ # @!method vertical_limit=(vertical_limit)
94
+ # @param vertical_limit [AIXM::Component::VerticalLimit]
95
+ has_one :vertical_limit
96
+
97
+ # @!method services
98
+ # @return [Array<AIXM::Component::Service>] services
99
+ # @!method add_service(service)
100
+ # @param service [AIXM::Component::Service]
101
+ has_many :services
102
+
103
+ # @!method airspace
104
+ # @return [AIXM::Feature::Airspace] airspace the layer defines
105
+ belongs_to :airspace
106
+
88
107
  # @return [String, nil] four letter location identifier as published in the ICAO DOC 7910
89
108
  attr_reader :location_indicator
90
109
 
91
- # @return [AIXM::Component::VerticalLimits] vertical limits of this layer
92
- attr_reader :vertical_limits
93
-
94
110
  # @return [String, nil] primary activity (e.g. "GLIDER")
95
111
  attr_reader :activity
96
112
 
@@ -100,21 +116,19 @@ module AIXM
100
116
  # @return [String, nil] free text remarks
101
117
  attr_reader :remarks
102
118
 
103
- def initialize(class: nil, location_indicator: nil, vertical_limits:)
119
+ def initialize(class: nil, location_indicator: nil, vertical_limit:)
104
120
  self.class = binding.local_variable_get(:class)
105
- self.location_indicator, self.vertical_limits = location_indicator, vertical_limits
121
+ self.location_indicator, self.vertical_limit = location_indicator, vertical_limit
106
122
  self.selective = false
107
123
  end
108
124
 
109
125
  # @return [String]
110
126
  def inspect
111
- %Q(#<#{original_class} class=#{@klass.inspect}>)
127
+ %Q(#<#{__class__} class=#{@klass.inspect}>)
112
128
  end
113
129
 
114
130
  # @!attribute class
115
- # @note Use +original_class+ to query the Ruby object class.
116
131
  # @return [Symbol] class of layer (see {CLASSES})
117
- alias_method :original_class, :class
118
132
  def class
119
133
  @klass
120
134
  end
@@ -129,11 +143,6 @@ module AIXM
129
143
  @location_indicator = value&.uptrans
130
144
  end
131
145
 
132
- def vertical_limits=(value)
133
- fail(ArgumentError, "invalid vertical limits") unless value.is_a? AIXM::Component::VerticalLimits
134
- @vertical_limits = value
135
- end
136
-
137
146
  def activity=(value)
138
147
  @activity = value.nil? ? nil : ACTIVITIES.lookup(value.to_s.to_sym, nil) || fail(ArgumentError, "invalid activity")
139
148
  end
@@ -164,9 +173,9 @@ module AIXM
164
173
  builder.codeClass(self.class.to_s) if self.class
165
174
  builder.codeLocInd(location_indicator) if location_indicator
166
175
  if activity
167
- builder.codeActivity(ACTIVITIES.key(activity).to_s.then_if(AIXM.aixm?) { |a| { 'AIRMODEL' => 'UAV', 'WINCH' => 'GLIDER' }[a] || a })
176
+ builder.codeActivity(ACTIVITIES.key(activity).to_s.then_if(AIXM.aixm?) { { 'AIRMODEL' => 'UAV', 'WINCH' => 'GLIDER' }[_1] || _1 })
168
177
  end
169
- builder << vertical_limits.to_xml
178
+ builder << vertical_limit.to_xml
170
179
  builder << timetable.to_xml(as: :Att) if timetable
171
180
  builder.codeSelAvbl(selective? ? 'Y' : 'N') if AIXM.ofmx?
172
181
  builder.txtRmk(remarks) if remarks