aixm 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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")