aixm 0.1.3 → 0.2.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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -0
  3. data/README.md +91 -11
  4. data/lib/aixm.rb +10 -0
  5. data/lib/aixm/base.rb +10 -0
  6. data/lib/aixm/component/base.rb +1 -1
  7. data/lib/aixm/component/class_layer.rb +0 -3
  8. data/lib/aixm/component/geometry.rb +0 -3
  9. data/lib/aixm/component/geometry/arc.rb +4 -8
  10. data/lib/aixm/component/geometry/base.rb +8 -0
  11. data/lib/aixm/component/geometry/border.rb +3 -8
  12. data/lib/aixm/component/geometry/circle.rb +5 -9
  13. data/lib/aixm/component/geometry/point.rb +6 -13
  14. data/lib/aixm/component/schedule.rb +8 -10
  15. data/lib/aixm/component/vertical_limits.rb +1 -4
  16. data/lib/aixm/document.rb +9 -6
  17. data/lib/aixm/f.rb +41 -0
  18. data/lib/aixm/feature/airspace.rb +5 -9
  19. data/lib/aixm/feature/base.rb +6 -0
  20. data/lib/aixm/feature/navigational_aid/base.rb +46 -0
  21. data/lib/aixm/feature/navigational_aid/designated_point.rb +69 -0
  22. data/lib/aixm/feature/navigational_aid/dme.rb +54 -0
  23. data/lib/aixm/feature/navigational_aid/marker.rb +41 -0
  24. data/lib/aixm/feature/navigational_aid/ndb.rb +56 -0
  25. data/lib/aixm/feature/navigational_aid/tacan.rb +54 -0
  26. data/lib/aixm/feature/navigational_aid/vor.rb +92 -0
  27. data/lib/aixm/refinements.rb +23 -2
  28. data/lib/aixm/shortcuts.rb +12 -5
  29. data/lib/aixm/version.rb +1 -1
  30. data/lib/aixm/xy.rb +9 -6
  31. data/lib/aixm/z.rb +22 -11
  32. data/spec/factory.rb +87 -4
  33. data/spec/lib/aixm/component/class_layer_spec.rb +6 -6
  34. data/spec/lib/aixm/component/geometry/arc_spec.rb +16 -16
  35. data/spec/lib/aixm/component/geometry/border_spec.rb +4 -4
  36. data/spec/lib/aixm/component/geometry/circle_spec.rb +10 -10
  37. data/spec/lib/aixm/component/geometry/point_spec.rb +4 -4
  38. data/spec/lib/aixm/component/geometry_spec.rb +21 -21
  39. data/spec/lib/aixm/component/schedule_spec.rb +6 -6
  40. data/spec/lib/aixm/component/vertical_limits_spec.rb +18 -18
  41. data/spec/lib/aixm/document_spec.rb +220 -30
  42. data/spec/lib/aixm/f_spec.rb +58 -0
  43. data/spec/lib/aixm/feature/airspace_spec.rb +5 -5
  44. data/spec/lib/aixm/feature/navigational_aid/base_spec.rb +37 -0
  45. data/spec/lib/aixm/feature/navigational_aid/designated_point_spec.rb +43 -0
  46. data/spec/lib/aixm/feature/navigational_aid/dme_spec.rb +43 -0
  47. data/spec/lib/aixm/feature/navigational_aid/marker_spec.rb +44 -0
  48. data/spec/lib/aixm/feature/navigational_aid/ndb_spec.rb +54 -0
  49. data/spec/lib/aixm/feature/navigational_aid/tacan_spec.rb +43 -0
  50. data/spec/lib/aixm/feature/navigational_aid/vor_spec.rb +58 -0
  51. data/spec/lib/aixm/refinements_spec.rb +27 -0
  52. data/spec/lib/aixm/xy_spec.rb +29 -23
  53. data/spec/lib/aixm/z_spec.rb +33 -17
  54. metadata +29 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c00283d4f8eeb7bc39a916e5d71778bcb9398ccd27d8bd0dd118b452f4d897b6
4
- data.tar.gz: 3d8c7cdf302994e590add9864ac684e98147fdc546e5ca3983bd5f68d498e3ea
3
+ metadata.gz: bd29f2661b79750343e05d494102c232fa91ffa861038eb4fe2b147fe2a01bd2
4
+ data.tar.gz: 657c897f48236120da2c82b833f65e8e540585176c46c939b1b9a73a594f13fd
5
5
  SHA512:
6
- metadata.gz: 0adb07ef827f44488bb89739155ee4c038a300f18590ba652d1a06771fefb4b8b72d50a203c4790d3d8a551f4c5992fcca8d73de68c50cd6c1d4732505ffeb1f
7
- data.tar.gz: a3f7cc1facbbae82eddf970e0eb240753c46f0cc4194c477ff44a0537ff5724764179a09ab9366cdf37665b5df7e2dfb2dae9431f4c8d0500aa1144a4a4b6437
6
+ metadata.gz: a356611cb807985b0dba0cde0fc5ced0ec07b84a9be92608145f32ea736a6d87f283d523855276e8902bb420575e80acca2d9f2109d424348f2c8771593c1a05
7
+ data.tar.gz: 0d98d537ced8fdea59cae71328bb684144e4c52c684f895b076a401ca39138f64683b796e8ba6486244f326662be9df30851fbf3c7819f4a8489b0c1315edeb0
@@ -1,3 +1,17 @@
1
+ ## 0.2.0
2
+
3
+ * Additions:
4
+ * Frequency
5
+ * Navigational aids
6
+ * `AIXM::Z#qfe?` and friends
7
+ * Breaking major changes:
8
+ * Symbols such as :qnh, :ofm or :mhz are downcased now
9
+
10
+ ## 0.1.4
11
+
12
+ * Breaking minor changes:
13
+ * `AIXM.z(alt: 123, code: :QNE)` is now `AIXM.z(123, :QNE)`
14
+
1
15
  ## 0.1.3
2
16
 
3
17
  * Breaking major changes:
data/README.md CHANGED
@@ -31,13 +31,13 @@ You can initialize all elements either traditionally or by use of shorter
31
31
  AIXM class methods:
32
32
 
33
33
  ```ruby
34
- AIXM::Feature::Airspace.new(...)
34
+ AIXM.airspace(...)
35
35
  AIXM.airspace(...)
36
36
  ```
37
37
 
38
38
  ### Fundamentals
39
39
 
40
- All fundamentals are bundled at the root of the module `AIXM`.
40
+ All fundamentals are subclasses of `AIXM::Base`.
41
41
 
42
42
  ### Document
43
43
 
@@ -77,14 +77,20 @@ AIXM.xy(lat: 11.375955555555556, long: -111.37595555555555)
77
77
  Altitudes and heights exist in three different forms:
78
78
 
79
79
  ```ruby
80
- AIXM.z(alt: 1000, code: :QFE) # height: 1000ft above ground
81
- AIXM.z(alt: 2000, code: :QNH) # altitude: of 2000ft above mean sea level
82
- AIXM.z(alt: 45, code: :QNE) # altitude: flight level 45
80
+ AIXM.z(1000, :qfe) # height: 1000ft above ground
81
+ AIXM.z(2000, :qnh) # altitude: of 2000ft above mean sea level
82
+ AIXM.z(45, :qne) # altitude: flight level 45
83
+ ```
84
+
85
+ #### Frequency
86
+
87
+ ```ruby
88
+ AIXM.f(123.35, :mhz)
83
89
  ```
84
90
 
85
91
  ### Features
86
92
 
87
- All features are subclasses of `AIXM::Feature`.
93
+ All features are subclasses of `AIXM::Feature::Base`.
88
94
 
89
95
  #### Airspace
90
96
 
@@ -97,9 +103,72 @@ All features are subclasses of `AIXM::Feature`.
97
103
  * class_layers << AIXM.class_layer
98
104
  * remarks = String
99
105
 
106
+ #### Navigational Aids
107
+
108
+ ##### Designated Point
109
+
110
+ * AIXM.designated_point
111
+ * id: String
112
+ * name: String
113
+ * xy: AIXM.xy
114
+ * z: AIXM.z or *nil*
115
+ * type: :icao, :adhp, :coordinates or :other
116
+ * remarks = String
117
+
118
+ ##### DME
119
+
120
+ * AIXM.dme
121
+ * id: String
122
+ * name: String
123
+ * xy: AIXM.xy
124
+ * z: AIXM.z or *nil*
125
+ * channel: String
126
+ * remarks = String
127
+
128
+ ##### NDB
129
+
130
+ * AIXM.ndb
131
+ * id: String
132
+ * name: String
133
+ * xy: AIXM.xy
134
+ * z: AIXM.z or *nil*
135
+ * f: AIXM.f
136
+ * remarks = String
137
+
138
+ ##### Marker
139
+
140
+ * AIXM.marker
141
+ * id: String
142
+ * name: String
143
+ * xy: AIXM.xy
144
+ * z: AIXM.z or *nil*
145
+ * remarks = String
146
+
147
+ ##### TACAN
148
+
149
+ * AIXM.tacan
150
+ * id: String
151
+ * name: String
152
+ * xy: AIXM.xy
153
+ * z: AIXM.z or *nil*
154
+ * channel: String
155
+ * remarks = String
156
+
157
+ ##### VOR and DVOR
158
+
159
+ * AIXM.vor
160
+ * id: String
161
+ * name: String
162
+ * xy: AIXM.xy
163
+ * z: AIXM.z or *nil*
164
+ * type: :vor or :vordme
165
+ * f: AIXM.f
166
+ * north: :geographic or :magnetic
167
+ * remarks = String
168
+
100
169
  ### Components
101
170
 
102
- All components are subclasses of `AIXM::Component`.
171
+ All components are subclasses of `AIXM::Component::Base`.
103
172
 
104
173
  #### Schedule
105
174
 
@@ -148,16 +217,21 @@ For a geometry to be complete, it must be comprised of either:
148
217
 
149
218
  ## Validation
150
219
 
151
- * Use `AIXM::Document#complete?` to check whether all mandatory information is
220
+ Use `AIXM::Document#complete?` to check whether all mandatory information is
152
221
  present. Airspaces, geometries etc have `complete?` methods as well.
153
- * Use `AIXM::Document#valid?` to validate the resulting AIXM against the XSD
154
- schema. If any, you find the errors in `AIXM::Document#errors`.
222
+
223
+ Use `AIXM::Document#valid?` to validate the resulting AIXM against the XSD
224
+ schema. If any, you find the errors in `AIXM::Document#errors`. Since the data
225
+ model is not fully implemented, some associations cannot be assigned and have
226
+ to be left empty. The resulting validation errors are silently ignored:
227
+
228
+ * OrgUid - organizations may be empty tags
155
229
 
156
230
  ## Rendering
157
231
 
158
232
  ```ruby
159
233
  document.to_xml # render AIXM 4.5 compliant XML
160
- document.to_xml(:OFM) # render AIXM 4.5 + OFM extensions XML
234
+ document.to_xml(:ofm) # render AIXM 4.5 + OFM extensions XML
161
235
  ```
162
236
 
163
237
  ## Constants
@@ -170,6 +244,7 @@ document.to_xml(:OFM) # render AIXM 4.5 + OFM extensions XML
170
244
 
171
245
  By `using AIXM::Refinements` you get the following general purpose methods:
172
246
 
247
+ * `Hash#lookup(key, default)`<br>Similar to `fetch` but falls back to values
173
248
  * `String#indent(number)`<br>Indent every line of a string with *number* spaces
174
249
  * `String#uptrans`<br>upcase and transliterate to match the reduced character set for names
175
250
  * `String#to_dd`<br>Convert DMS angle to DD or `nil` if the format is not recognized
@@ -177,6 +252,9 @@ By `using AIXM::Refinements` you get the following general purpose methods:
177
252
  * `Float#trim`<br>Convert whole numbers to Integer and leave all other untouched
178
253
  * `Float#to_km(from: unit)`<br>Convert a distance from *unit* (:km, :m, :nm or :ft) to km
179
254
 
255
+ See the [source code](https://github.com/svoop/aixm/blob/master/lib/aixm/refinements.rb)
256
+ for more explicit descriptions and examples.
257
+
180
258
  ## Extensions
181
259
 
182
260
  ### OFM
@@ -194,6 +272,8 @@ originative suite:
194
272
 
195
273
  * [AIXM](http://aixm.aero)
196
274
  * [AIXM on Wikipedia](https://en.wikipedia.org/wiki/AIXM)
275
+ * [AIXM 4.5 Specification](http://aixm.aero/document/aixm-45-specification)
276
+ * [AICM 4.5 Entity-Relationship](https://www.ead.eurocontrol.int/SystemHelp/mergedProjects/SDO/aixm/)
197
277
  * [Open Flightmaps](https://openflightmaps.org)
198
278
 
199
279
  ## Tests
@@ -8,9 +8,11 @@ require 'time'
8
8
  require_relative 'aixm/version'
9
9
  require_relative 'aixm/refinements'
10
10
 
11
+ require_relative 'aixm/base'
11
12
  require_relative 'aixm/document'
12
13
  require_relative 'aixm/xy'
13
14
  require_relative 'aixm/z'
15
+ require_relative 'aixm/f'
14
16
 
15
17
  require_relative 'aixm/component/base'
16
18
  require_relative 'aixm/component/geometry'
@@ -22,6 +24,14 @@ require_relative 'aixm/component/class_layer'
22
24
  require_relative 'aixm/component/vertical_limits'
23
25
  require_relative 'aixm/component/schedule'
24
26
 
27
+ require_relative 'aixm/feature/base'
25
28
  require_relative 'aixm/feature/airspace'
29
+ require_relative 'aixm/feature/navigational_aid/base'
30
+ require_relative 'aixm/feature/navigational_aid/designated_point'
31
+ require_relative 'aixm/feature/navigational_aid/dme'
32
+ require_relative 'aixm/feature/navigational_aid/marker'
33
+ require_relative 'aixm/feature/navigational_aid/ndb'
34
+ require_relative 'aixm/feature/navigational_aid/tacan'
35
+ require_relative 'aixm/feature/navigational_aid/vor'
26
36
 
27
37
  require_relative 'aixm/shortcuts'
@@ -0,0 +1,10 @@
1
+ module AIXM
2
+ class Base
3
+ using AIXM::Refinements
4
+
5
+ def format_for(*extensions)
6
+ extensions >> :ofm ? :ofm : :aixm
7
+ end
8
+
9
+ end
10
+ end
@@ -1,6 +1,6 @@
1
1
  module AIXM
2
2
  module Component
3
- class Base
3
+ class Base < AIXM::Base
4
4
  end
5
5
  end
6
6
  end
@@ -34,9 +34,6 @@ module AIXM
34
34
 
35
35
  ##
36
36
  # Render AIXM
37
- #
38
- # Extensions:
39
- # * +:OFM+ - Open Flightmaps
40
37
  def to_xml(*extensions)
41
38
  builder = Builder::XmlMarkup.new(indent: 2)
42
39
  builder.codeClass(self.class.to_s) if self.class
@@ -47,9 +47,6 @@ module AIXM
47
47
 
48
48
  ##
49
49
  # Render AIXM
50
- #
51
- # Extensions:
52
- # * +:OFM+ - Open Flightmaps
53
50
  def to_xml(*extensions)
54
51
  @result_array.map { |h| h.to_xml(*extensions) }.join
55
52
  end
@@ -31,19 +31,15 @@ module AIXM
31
31
 
32
32
  ##
33
33
  # Render AIXM
34
- #
35
- # Extensions:
36
- # * +:OFM+ - Open Flightmaps
37
34
  def to_xml(*extensions)
38
- format = extensions >> :OFM ? :OFM : :AIXM
39
35
  builder = Builder::XmlMarkup.new(indent: 2)
40
36
  builder.Avx do |avx|
41
37
  avx.codeType(clockwise? ? 'CWA' : 'CCA')
42
- avx.geoLat(xy.lat(format))
43
- avx.geoLong(xy.long(format))
38
+ avx.geoLat(xy.lat(format_for(*extensions)))
39
+ avx.geoLong(xy.long(format_for(*extensions)))
44
40
  avx.codeDatum('WGE')
45
- avx.geoLatArc(center_xy.lat(format))
46
- avx.geoLongArc(center_xy.long(format))
41
+ avx.geoLatArc(center_xy.lat(format_for(*extensions)))
42
+ avx.geoLongArc(center_xy.long(format_for(*extensions)))
47
43
  end
48
44
  end
49
45
  end
@@ -0,0 +1,8 @@
1
+ module AIXM
2
+ module Component
3
+ class Geometry
4
+ class Base < AIXM::Component::Base
5
+ end
6
+ end
7
+ end
8
+ end
@@ -23,19 +23,14 @@ module AIXM
23
23
 
24
24
  ##
25
25
  # Render AIXM
26
- #
27
- # Extensions:
28
- # * +:OFM+ - Open Flightmaps
29
26
  def to_xml(*extensions)
30
- format = extensions >> :OFM ? :OFM : :AIXM
31
27
  builder = Builder::XmlMarkup.new(indent: 2)
32
28
  builder.Avx do |avx|
33
29
  avx.codeType('FNT')
34
- avx.geoLat(xy.lat(format))
35
- avx.geoLong(xy.long(format))
30
+ avx.geoLat(xy.lat(format_for(*extensions)))
31
+ avx.geoLong(xy.long(format_for(*extensions)))
36
32
  avx.codeDatum('WGE')
37
- # TODO: Find examples how to do this with vanilla AIXM
38
- if extensions >> :OFM
33
+ if extensions >> :ofm
39
34
  avx.GbrUid do |gbruid|
40
35
  gbruid.txtName(name.to_s)
41
36
  end
@@ -4,7 +4,7 @@ module AIXM
4
4
 
5
5
  ##
6
6
  # Circles are defined by a +center_xy+ and a +radius+ in kilometers.
7
- class Circle
7
+ class Circle < Base
8
8
  using AIXM::Refinements
9
9
 
10
10
  attr_reader :center_xy, :radius
@@ -22,19 +22,15 @@ module AIXM
22
22
 
23
23
  ##
24
24
  # Render AIXM
25
- #
26
- # Extensions:
27
- # * +:OFM+ - Open Flightmaps
28
25
  def to_xml(*extensions)
29
- format = extensions >> :OFM ? :OFM : :AIXM
30
26
  builder = Builder::XmlMarkup.new(indent: 2)
31
27
  builder.Avx do |avx|
32
28
  avx.codeType('CWA')
33
- avx.geoLat(north_xy.lat(format))
34
- avx.geoLong(north_xy.long(format))
29
+ avx.geoLat(north_xy.lat(format_for(*extensions)))
30
+ avx.geoLong(north_xy.long(format_for(*extensions)))
35
31
  avx.codeDatum('WGE')
36
- avx.geoLatArc(center_xy.lat(format))
37
- avx.geoLongArc(center_xy.long(format))
32
+ avx.geoLatArc(center_xy.lat(format_for(*extensions)))
33
+ avx.geoLongArc(center_xy.long(format_for(*extensions)))
38
34
  end
39
35
  end
40
36
 
@@ -4,9 +4,12 @@ module AIXM
4
4
 
5
5
  ##
6
6
  # Points are defined by +xy+ coordinates.
7
- class Point
7
+ class Point < Base
8
+ extend Forwardable
8
9
  using AIXM::Refinements
9
10
 
11
+ def_delegators :xy, :to_digest
12
+
10
13
  attr_reader :xy
11
14
 
12
15
  def initialize(xy:)
@@ -14,24 +17,14 @@ module AIXM
14
17
  @xy = xy
15
18
  end
16
19
 
17
- ##
18
- # Digest to identify the payload
19
- def to_digest
20
- [xy.lat, xy.long].to_digest
21
- end
22
-
23
20
  ##
24
21
  # Render AIXM
25
- #
26
- # Extensions:
27
- # * +:OFM+ - Open Flightmaps
28
22
  def to_xml(*extensions)
29
- format = extensions >> :OFM ? :OFM : :AIXM
30
23
  builder = Builder::XmlMarkup.new(indent: 2)
31
24
  builder.Avx do |avx|
32
25
  avx.codeType('GRC')
33
- avx.geoLat(xy.lat(format))
34
- avx.geoLong(xy.long(format))
26
+ avx.geoLat(xy.lat(format_for(*extensions)))
27
+ avx.geoLong(xy.long(format_for(*extensions)))
35
28
  avx.codeDatum('WGE')
36
29
  end
37
30
  end
@@ -12,20 +12,18 @@ module AIXM
12
12
  using AIXM::Refinements
13
13
 
14
14
  CODES = {
15
- continuous: :H24,
16
- sunrise_to_sunset: :HJ,
17
- sunset_to_sunrise: :HN,
18
- unspecified: :HX,
19
- operational_request: :HO,
20
- notam: :NOTAM
15
+ H24: :continuous,
16
+ HJ: :sunrise_to_sunset,
17
+ HN: :sunset_to_sunrise,
18
+ HX: :unspecified,
19
+ HO: :operational_request,
20
+ NOTAM: :notam
21
21
  }.freeze
22
22
 
23
23
  attr_reader :code
24
24
 
25
25
  def initialize(code:)
26
- @code = code&.to_sym
27
- @code = CODES[code] unless CODES.has_value? code
28
- fail(ArgumentError, "code `#{code}' not recognized") unless @code
26
+ @code = CODES.lookup(code&.to_sym, nil) || fail(ArgumentError, "invalid code")
29
27
  end
30
28
 
31
29
  ##
@@ -37,7 +35,7 @@ module AIXM
37
35
  ##
38
36
  # Render AIXM
39
37
  def to_xml(*extensions)
40
- Builder::XmlMarkup.new(indent: 2).codeWorkHr(code.to_s)
38
+ Builder::XmlMarkup.new(indent: 2).codeWorkHr(CODES.key(code).to_s)
41
39
  end
42
40
  end
43
41
 
@@ -16,7 +16,7 @@ module AIXM
16
16
  using AIXM::Refinements
17
17
 
18
18
  TAGS = { upper: :Upper, lower: :Lower, max: :Max, min: :Mnm }.freeze
19
- CODES = { QFE: :HEI, QNH: :ALT, QNE: :STD }.freeze
19
+ CODES = { qfe: :HEI, qnh: :ALT, qne: :STD }.freeze
20
20
 
21
21
  attr_reader :upper_z, :lower_z, :max_z, :min_z
22
22
 
@@ -36,9 +36,6 @@ module AIXM
36
36
 
37
37
  ##
38
38
  # Render AIXM
39
- #
40
- # Extensions:
41
- # * +:OFM+ - Open Flightmaps
42
39
  def to_xml(*extensions)
43
40
  %i(upper lower max min).each_with_object(Builder::XmlMarkup.new(indent: 2)) do |limit, builder|
44
41
  if z = send(:"#{limit}_z")