aixm 0.3.7 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +72 -6
  4. data/README.md +191 -53
  5. data/exe/ckmid +11 -0
  6. data/exe/mkmid +11 -0
  7. data/lib/aixm/association.rb +367 -0
  8. data/lib/aixm/classes.rb +44 -0
  9. data/lib/aixm/component/fato.rb +44 -52
  10. data/lib/aixm/component/frequency.rb +13 -14
  11. data/lib/aixm/component/geometry/arc.rb +2 -2
  12. data/lib/aixm/component/geometry/border.rb +14 -5
  13. data/lib/aixm/component/geometry/circle.rb +8 -2
  14. data/lib/aixm/component/geometry/point.rb +10 -3
  15. data/lib/aixm/component/geometry/rhumb_line.rb +54 -0
  16. data/lib/aixm/component/geometry.rb +38 -38
  17. data/lib/aixm/component/helipad.rb +29 -37
  18. data/lib/aixm/component/layer.rb +28 -19
  19. data/lib/aixm/component/lighting.rb +11 -12
  20. data/lib/aixm/component/runway.rb +46 -53
  21. data/lib/aixm/{feature → component}/service.rb +36 -35
  22. data/lib/aixm/component/surface.rb +3 -3
  23. data/lib/aixm/component/timetable.rb +5 -3
  24. data/lib/aixm/component/{vertical_limits.rb → vertical_limit.rb} +12 -6
  25. data/lib/aixm/config.rb +6 -3
  26. data/lib/aixm/document.rb +31 -49
  27. data/lib/aixm/executables.rb +85 -0
  28. data/lib/aixm/f.rb +28 -0
  29. data/lib/aixm/feature/address.rb +20 -15
  30. data/lib/aixm/feature/airport.rb +113 -129
  31. data/lib/aixm/feature/airspace.rb +54 -23
  32. data/lib/aixm/feature/navigational_aid/designated_point.rb +12 -14
  33. data/lib/aixm/feature/navigational_aid/dme.rb +10 -11
  34. data/lib/aixm/feature/navigational_aid/marker.rb +6 -2
  35. data/lib/aixm/feature/navigational_aid/ndb.rb +6 -2
  36. data/lib/aixm/feature/navigational_aid/tacan.rb +6 -2
  37. data/lib/aixm/feature/navigational_aid/vor.rb +22 -14
  38. data/lib/aixm/feature/navigational_aid.rb +7 -9
  39. data/lib/aixm/feature/obstacle.rb +22 -20
  40. data/lib/aixm/feature/obstacle_group.rb +30 -30
  41. data/lib/aixm/feature/organisation.rb +20 -4
  42. data/lib/aixm/feature/unit.rb +35 -45
  43. data/lib/aixm/feature.rb +13 -3
  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 +34 -50
  48. data/lib/aixm/shortcuts.rb +6 -43
  49. data/lib/aixm/version.rb +1 -1
  50. data/lib/aixm/xy.rb +9 -1
  51. data/lib/aixm.rb +18 -7
  52. data/schemas/ofmx/{0 → 0.1}/OFMX-CSV-Obstacle.json +0 -0
  53. data/schemas/ofmx/{0 → 0.1}/OFMX-CSV.json +0 -0
  54. data/schemas/ofmx/{0 → 0.1}/OFMX-DataTypes.xsd +52 -2
  55. data/schemas/ofmx/{0 → 0.1}/OFMX-Features.xsd +225 -14
  56. data/schemas/ofmx/{0 → 0.1}/OFMX-Snapshot.xsd +0 -5
  57. data.tar.gz.sig +0 -0
  58. metadata +116 -164
  59. metadata.gz.sig +0 -0
  60. data/.gitignore +0 -6
  61. data/.ruby-version +0 -1
  62. data/.travis.yml +0 -8
  63. data/.yardopts +0 -3
  64. data/Guardfile +0 -8
  65. data/aixm.gemspec +0 -35
  66. data/gems.rb +0 -3
  67. data/lib/aixm/component.rb +0 -6
  68. data/rakefile.rb +0 -22
  69. data/spec/factory.rb +0 -559
  70. data/spec/lib/aixm/a_spec.rb +0 -203
  71. data/spec/lib/aixm/component/fato_spec.rb +0 -260
  72. data/spec/lib/aixm/component/frequency_spec.rb +0 -75
  73. data/spec/lib/aixm/component/geometry/arc_spec.rb +0 -75
  74. data/spec/lib/aixm/component/geometry/border_spec.rb +0 -33
  75. data/spec/lib/aixm/component/geometry/circle_spec.rb +0 -70
  76. data/spec/lib/aixm/component/geometry/point_spec.rb +0 -39
  77. data/spec/lib/aixm/component/geometry_spec.rb +0 -321
  78. data/spec/lib/aixm/component/helipad_spec.rb +0 -187
  79. data/spec/lib/aixm/component/layer_spec.rb +0 -137
  80. data/spec/lib/aixm/component/lighting_spec.rb +0 -88
  81. data/spec/lib/aixm/component/runway_spec.rb +0 -472
  82. data/spec/lib/aixm/component/surface_spec.rb +0 -124
  83. data/spec/lib/aixm/component/timetable_spec.rb +0 -49
  84. data/spec/lib/aixm/component/vertical_limits_spec.rb +0 -97
  85. data/spec/lib/aixm/config_spec.rb +0 -41
  86. data/spec/lib/aixm/d_spec.rb +0 -150
  87. data/spec/lib/aixm/document_spec.rb +0 -1875
  88. data/spec/lib/aixm/errors_spec.rb +0 -14
  89. data/spec/lib/aixm/f_spec.rb +0 -85
  90. data/spec/lib/aixm/feature/address_spec.rb +0 -55
  91. data/spec/lib/aixm/feature/airport_spec.rb +0 -770
  92. data/spec/lib/aixm/feature/airspace_spec.rb +0 -390
  93. data/spec/lib/aixm/feature/navigational_aid/designated_point_spec.rb +0 -98
  94. data/spec/lib/aixm/feature/navigational_aid/dme_spec.rb +0 -92
  95. data/spec/lib/aixm/feature/navigational_aid/marker_spec.rb +0 -79
  96. data/spec/lib/aixm/feature/navigational_aid/ndb_spec.rb +0 -89
  97. data/spec/lib/aixm/feature/navigational_aid/tacan_spec.rb +0 -88
  98. data/spec/lib/aixm/feature/navigational_aid/vor_spec.rb +0 -245
  99. data/spec/lib/aixm/feature/navigational_aid_spec.rb +0 -52
  100. data/spec/lib/aixm/feature/obstacle_group_spec.rb +0 -326
  101. data/spec/lib/aixm/feature/obstacle_spec.rb +0 -279
  102. data/spec/lib/aixm/feature/organisation_spec.rb +0 -77
  103. data/spec/lib/aixm/feature/service_spec.rb +0 -59
  104. data/spec/lib/aixm/feature/unit_spec.rb +0 -230
  105. data/spec/lib/aixm/feature_spec.rb +0 -38
  106. data/spec/lib/aixm/p_spec.rb +0 -189
  107. data/spec/lib/aixm/refinements_spec.rb +0 -381
  108. data/spec/lib/aixm/version_spec.rb +0 -7
  109. data/spec/lib/aixm/w_spec.rb +0 -150
  110. data/spec/lib/aixm/xy_spec.rb +0 -180
  111. data/spec/lib/aixm/z_spec.rb +0 -94
  112. data/spec/macros/marking.rb +0 -12
  113. data/spec/macros/organisation.rb +0 -11
  114. data/spec/macros/remarks.rb +0 -12
  115. data/spec/macros/timetable.rb +0 -11
  116. data/spec/macros/xy.rb +0 -11
  117. data/spec/macros/z_qnh.rb +0 -11
  118. data/spec/sounds/failure.mp3 +0 -0
  119. data/spec/sounds/success.mp3 +0 -0
  120. data/spec/spec_helper.rb +0 -55
@@ -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
 
@@ -33,13 +35,20 @@ module AIXM
33
35
  @name = value
34
36
  end
35
37
 
38
+ # @return [String] UID markup
39
+ def to_uid(as: :GbrUid)
40
+ builder = Builder::XmlMarkup.new(indent: 2)
41
+ builder.tag!(as) do |tag|
42
+ tag.txtName(name.to_s)
43
+ end
44
+ end
45
+ memoize :to_uid
46
+
36
47
  # @return [String] AIXM or OFMX markup
37
48
  def to_xml
38
49
  builder = Builder::XmlMarkup.new(indent: 2)
39
50
  builder.Avx do |avx|
40
- avx.GbrUid do |gbr_uid|
41
- gbr_uid.txtName(name.to_s)
42
- end
51
+ avx << to_uid.indent(2)
43
52
  avx.codeType('FNT')
44
53
  avx.geoLat(xy.lat(AIXM.schema))
45
54
  avx.geoLong(xy.long(AIXM.schema))
@@ -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 this segment 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,18 +1,25 @@
1
1
  using AIXM::Refinements
2
2
 
3
3
  module AIXM
4
- class Component
4
+ module Component
5
5
  class Geometry
6
6
 
7
- # Points are defined by {#xy} coordinates.
7
+ # Either an individual point or the starting point of a great circle
8
+ # line. Defined by {#xy} coordinates.
8
9
  #
9
10
  # ===Cheat Sheet in Pseudo Code:
10
11
  # point = AIXM.point(
11
12
  # xy: AIXM.xy
12
13
  # )
13
14
  #
14
- # @see https://github.com/openflightmaps/ofmx/wiki/Airspace#point
15
+ # @see https://gitlab.com/openflightmaps/ofmx/wikis/Airspace#point
15
16
  class Point
17
+ include AIXM::Association
18
+
19
+ # @!method geometry
20
+ # @return [AIXM::Component::Geometry] geometry this segment belongs to
21
+ belongs_to :geometry, as: :segment
22
+
16
23
  # @return [AIXM::XY] (starting) point
17
24
  attr_reader :xy
18
25
 
@@ -0,0 +1,54 @@
1
+ using AIXM::Refinements
2
+
3
+ module AIXM
4
+ module Component
5
+ class Geometry
6
+
7
+ # Starting point of a rhumb line which describes a spiral on a sphere
8
+ # crossing all meridians at the same angle. Defined by {#xy} coordinates.
9
+ #
10
+ # ===Cheat Sheet in Pseudo Code:
11
+ # point = AIXM.rhumb_line(
12
+ # xy: AIXM.xy
13
+ # )
14
+ #
15
+ # @see https://gitlab.com/openflightmaps/ofmx/wikis/Airspace#rhumb-line
16
+ class RhumbLine
17
+ include AIXM::Association
18
+
19
+ # @!method geometry
20
+ # @return [AIXM::Component::Geometry] geometry this segment belongs to
21
+ belongs_to :geometry, as: :segment
22
+
23
+ # @return [AIXM::XY] (starting) point
24
+ attr_reader :xy
25
+
26
+ def initialize(xy:)
27
+ self.xy = xy
28
+ end
29
+
30
+ # @return [String]
31
+ def inspect
32
+ %Q(#<#{self.class} xy="#{xy}">)
33
+ end
34
+
35
+ def xy=(value)
36
+ fail(ArgumentError, "invalid xy") unless value.is_a? AIXM::XY
37
+ @xy = value
38
+ end
39
+
40
+ # @return [String] AIXM or OFMX markup
41
+ def to_xml
42
+ builder = Builder::XmlMarkup.new(indent: 2)
43
+ builder.Avx do |avx|
44
+ avx.codeType('RHL')
45
+ avx.geoLat(xy.lat(AIXM.schema))
46
+ avx.geoLong(xy.long(AIXM.schema))
47
+ avx.codeDatum('WGE')
48
+ end
49
+ end
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -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,35 @@ 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::RhumbLine
35
+ # AIXM::Component::Geometry::Arc,
36
+ # AIXM::Component::Geometry::Circle,
37
+ # AIXM::Component::Geometry::Border>] points, rhumb lines, arcs, borders or circle
38
+ # @!method add_segment(segment)
39
+ # @param segment [AIXM::Component::Geometry::Point,
40
+ # AIXM::Component::Geometry::RhumbLine,
41
+ # AIXM::Component::Geometry::Arc,
42
+ # AIXM::Component::Geometry::Circle,
43
+ # AIXM::Component::Geometry::Border]
44
+ # @return [self]
45
+ has_many :segments, accept: %i(point rhumb_line arc circle border)
46
+
47
+ # @!method airspace
48
+ # @return [AIXM::Feature::Airspace] airspace the geometry defines
49
+ belongs_to :airspace
43
50
 
44
51
  def initialize(*segments)
45
- @result_array = segments
52
+ segments.each { add_segment(_1) }
46
53
  end
47
54
 
48
55
  # @return [String]
@@ -50,14 +57,6 @@ module AIXM
50
57
  %Q(#<#{self.class} segments=#{segments.count.inspect}>)
51
58
  end
52
59
 
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
60
  # @return [Boolean] whether the geometry is closed
62
61
  def closed?
63
62
  point? || circle? || polygon?
@@ -66,26 +65,27 @@ module AIXM
66
65
  # @return [String] AIXM or OFMX markup
67
66
  def to_xml
68
67
  fail(GeometryError.new("geometry is not closed", self)) unless closed?
69
- @result_array.map { |h| h.to_xml }.join
68
+ segments.map { _1.to_xml }.join
70
69
  end
71
70
 
72
- private
73
-
71
+ # @return [Boolean] Single point geometry?
74
72
  def point?
75
- @result_array.size == 1 &&
76
- @result_array.first.is_a?(AIXM::Component::Geometry::Point)
73
+ segments.size == 1 &&
74
+ segments.first.is_a?(AIXM::Component::Geometry::Point)
77
75
  end
78
76
 
77
+ # @return [Boolean] Circle shaped geometry?
79
78
  def circle?
80
- @result_array.size == 1 &&
81
- @result_array.first.is_a?(AIXM::Component::Geometry::Circle)
79
+ segments.size == 1 &&
80
+ segments.first.is_a?(AIXM::Component::Geometry::Circle)
82
81
  end
83
82
 
83
+ # @return [Boolean] Polygon shaped geometry?
84
84
  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
85
+ segments.size >= 3 &&
86
+ !segments.any? { _1.is_a?(AIXM::Component::Geometry::Circle) } &&
87
+ segments.last.is_a?(AIXM::Component::Geometry::Point) &&
88
+ segments.first.xy == segments.last.xy
89
89
  end
90
90
  end
91
91
 
@@ -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,17 +149,6 @@ 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)
@@ -166,6 +157,7 @@ module AIXM
166
157
  tla_uid.txtDesig(name)
167
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
@@ -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
  # Lighting of a runway, helipad etc
7
7
  #
@@ -14,10 +14,13 @@ module AIXM
14
14
  # lighting.color = COLORS or nil
15
15
  # lighting.remarks = String or nil
16
16
  #
17
- # @see https://github.com/openflightmaps/ofmx/wiki/Airport#rls-runway-direction-lighting
18
- # @see https://github.com/openflightmaps/ofmx/wiki/Airport#fls-fato-direction-lighting
19
- # @see https://github.com/openflightmaps/ofmx/wiki/Airport#tls-helipad-tlof-lighting
17
+ # @see https://gitlab.com/openflightmaps/ofmx/wikis/Airport#rls-runway-direction-lighting
18
+ # @see https://gitlab.com/openflightmaps/ofmx/wikis/Airport#fls-fato-direction-lighting
19
+ # @see https://gitlab.com/openflightmaps/ofmx/wikis/Airport#tls-helipad-tlof-lighting
20
20
  class Lighting
21
+ include AIXM::Association
22
+ include AIXM::Memoize
23
+
21
24
  POSITIONS = {
22
25
  TDZ: :touch_down_zone,
23
26
  AIM: :aiming_point,
@@ -54,8 +57,9 @@ module AIXM
54
57
  OTHER: :other # specify in remarks
55
58
  }
56
59
 
57
- # @return [AIXM::Component::Runway::Direction, AIXM::Component::FATO::Direction, AIXM::Component::Helipad] lighted entity
58
- attr_reader :lightable
60
+ # @!method lightable
61
+ # @return [AIXM::Component::Runway::Direction, AIXM::Component::FATO::Direction, AIXM::Component::Helipad] lighted entity
62
+ belongs_to :lightable
59
63
 
60
64
  # @return [Symbol, nil] position of the lighting system (see {POSITIONS})
61
65
  attr_reader :position
@@ -81,12 +85,6 @@ module AIXM
81
85
  %Q(#<#{self.class} position=#{position.inspect}>)
82
86
  end
83
87
 
84
- def lightable=(value)
85
- fail(ArgumentError, "invalid lightable") unless value.respond_to? :lightings
86
- @lightable = value
87
- end
88
- private :lightable=
89
-
90
88
  def position=(value)
91
89
  @position = POSITIONS.lookup(value.to_s.to_sym, nil) || fail(ArgumentError, "invalid position")
92
90
  end
@@ -115,6 +113,7 @@ module AIXM
115
113
  tag.codePsn(POSITIONS.key(position).to_s)
116
114
  end
117
115
  end
116
+ memoize :to_uid
118
117
 
119
118
  # @return [String] AIXM or OFMX markup
120
119
  def to_xml(as:)