aixm 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.ruby-version +1 -1
  4. data/.yardopts +3 -0
  5. data/CHANGELOG.md +34 -14
  6. data/Guardfile +1 -0
  7. data/README.md +64 -257
  8. data/lib/aixm.rb +16 -7
  9. data/lib/aixm/component.rb +6 -0
  10. data/lib/aixm/component/frequency.rb +135 -0
  11. data/lib/aixm/component/geometry.rb +34 -23
  12. data/lib/aixm/component/geometry/arc.rb +37 -22
  13. data/lib/aixm/component/geometry/border.rb +29 -20
  14. data/lib/aixm/component/geometry/circle.rb +39 -22
  15. data/lib/aixm/component/geometry/point.rb +29 -13
  16. data/lib/aixm/component/helipad.rb +154 -0
  17. data/lib/aixm/component/layer.rb +91 -0
  18. data/lib/aixm/component/runway.rb +294 -0
  19. data/lib/aixm/component/service.rb +170 -0
  20. data/lib/aixm/component/timetable.rb +65 -0
  21. data/lib/aixm/component/vertical_limits.rb +65 -29
  22. data/lib/aixm/config.rb +87 -0
  23. data/lib/aixm/document.rb +66 -42
  24. data/lib/aixm/errors.rb +11 -0
  25. data/lib/aixm/f.rb +34 -20
  26. data/lib/aixm/feature.rb +38 -0
  27. data/lib/aixm/feature/airport.rb +473 -0
  28. data/lib/aixm/feature/airspace.rb +145 -92
  29. data/lib/aixm/feature/navigational_aid.rb +94 -0
  30. data/lib/aixm/feature/navigational_aid/designated_point.rb +50 -54
  31. data/lib/aixm/feature/navigational_aid/dme.rb +48 -40
  32. data/lib/aixm/feature/navigational_aid/marker.rb +55 -45
  33. data/lib/aixm/feature/navigational_aid/ndb.rb +54 -50
  34. data/lib/aixm/feature/navigational_aid/tacan.rb +38 -31
  35. data/lib/aixm/feature/navigational_aid/vor.rb +84 -76
  36. data/lib/aixm/feature/organisation.rb +97 -0
  37. data/lib/aixm/feature/unit.rb +152 -0
  38. data/lib/aixm/refinements.rb +132 -47
  39. data/lib/aixm/shortcuts.rb +11 -6
  40. data/lib/aixm/version.rb +1 -1
  41. data/lib/aixm/xy.rb +64 -20
  42. data/lib/aixm/z.rb +51 -22
  43. data/{lib/aixm/schemas → schemas/aixm}/4.5/AIXM-DataTypes.xsd +0 -0
  44. data/{lib/aixm/schemas → schemas/aixm}/4.5/AIXM-Features.xsd +0 -0
  45. data/{lib/aixm/schemas → schemas/aixm}/4.5/AIXM-Snapshot.xsd +0 -0
  46. data/schemas/ofmx/0/OFMX-DataTypes.xsd +5077 -0
  47. data/schemas/ofmx/0/OFMX-Features.xsd +9955 -0
  48. data/schemas/ofmx/0/OFMX-Snapshot.xsd +217 -0
  49. data/spec/factory.rb +209 -33
  50. data/spec/lib/aixm/component/frequency_spec.rb +75 -0
  51. data/spec/lib/aixm/component/geometry/arc_spec.rb +28 -22
  52. data/spec/lib/aixm/component/geometry/border_spec.rb +23 -20
  53. data/spec/lib/aixm/component/geometry/circle_spec.rb +31 -22
  54. data/spec/lib/aixm/component/geometry/point_spec.rb +11 -14
  55. data/spec/lib/aixm/component/geometry_spec.rb +150 -69
  56. data/spec/lib/aixm/component/helipad_spec.rb +136 -0
  57. data/spec/lib/aixm/component/layer_spec.rb +110 -0
  58. data/spec/lib/aixm/component/runway_spec.rb +402 -0
  59. data/spec/lib/aixm/component/service_spec.rb +61 -0
  60. data/spec/lib/aixm/component/timetable_spec.rb +49 -0
  61. data/spec/lib/aixm/component/vertical_limits_spec.rb +39 -20
  62. data/spec/lib/aixm/config_spec.rb +41 -0
  63. data/spec/lib/aixm/document_spec.rb +637 -147
  64. data/spec/lib/aixm/errors_spec.rb +14 -0
  65. data/spec/lib/aixm/f_spec.rb +17 -10
  66. data/spec/lib/aixm/feature/airport_spec.rb +546 -0
  67. data/spec/lib/aixm/feature/airspace_spec.rb +349 -226
  68. data/spec/lib/aixm/feature/navigational_aid/designated_point_spec.rb +47 -36
  69. data/spec/lib/aixm/feature/navigational_aid/dme_spec.rb +61 -36
  70. data/spec/lib/aixm/feature/navigational_aid/marker_spec.rb +61 -113
  71. data/spec/lib/aixm/feature/navigational_aid/ndb_spec.rb +65 -79
  72. data/spec/lib/aixm/feature/navigational_aid/tacan_spec.rb +57 -36
  73. data/spec/lib/aixm/feature/navigational_aid/vor_spec.rb +86 -112
  74. data/spec/lib/aixm/feature/navigational_aid_spec.rb +52 -0
  75. data/spec/lib/aixm/feature/organisation_spec.rb +77 -0
  76. data/spec/lib/aixm/feature/unit_spec.rb +227 -0
  77. data/spec/lib/aixm/feature_spec.rb +58 -0
  78. data/spec/lib/aixm/refinements_spec.rb +187 -178
  79. data/spec/lib/aixm/xy_spec.rb +45 -34
  80. data/spec/lib/aixm/z_spec.rb +19 -21
  81. data/spec/macros/organisation.rb +11 -0
  82. data/spec/macros/remarks.rb +12 -0
  83. data/spec/macros/timetable.rb +11 -0
  84. data/spec/macros/xy.rb +11 -0
  85. data/spec/macros/z_qnh.rb +11 -0
  86. data/spec/spec_helper.rb +26 -0
  87. metadata +60 -19
  88. data/lib/aixm/base.rb +0 -10
  89. data/lib/aixm/component/base.rb +0 -6
  90. data/lib/aixm/component/class_layer.rb +0 -46
  91. data/lib/aixm/component/geometry/base.rb +0 -8
  92. data/lib/aixm/component/schedule.rb +0 -43
  93. data/lib/aixm/feature/base.rb +0 -6
  94. data/lib/aixm/feature/navigational_aid/base.rb +0 -79
  95. data/spec/lib/aixm/component/class_layer_spec.rb +0 -74
  96. data/spec/lib/aixm/component/schedule_spec.rb +0 -33
  97. data/spec/lib/aixm/feature/navigational_aid/base_spec.rb +0 -41
@@ -1,52 +1,70 @@
1
+ using AIXM::Refinements
2
+
1
3
  module AIXM
2
- module Feature
3
- module NavigationalAid
4
+ class Feature
5
+ class NavigationalAid
4
6
 
5
- ##
6
- # VOR (VHF omnidirectional range) operate in the frequency band between
7
- # 108.00 Mhz to 117.95 MHz. Two type of VORs exist:
8
- #
9
- # Types:
10
- # * +:vor+ (+:VOR+) - conventional VOR (also known as CVOR)
11
- # * +:doppler_vor+ (+:DVOR+) - Doppler VOR
7
+ # VHF omni directional radio range (VOR) is a type of radio navigation for
8
+ # aircraft to determine their position and course. They operate in the
9
+ # frequency band between 108.00 Mhz to 117.95 MHz.
12
10
  #
13
- # North types:
14
- # * +:geographic+ (+:TRUE+) - VOR aligned towards geographic north
15
- # * +:grid+ (+:GRID+) - VOR aligned along north-south lines of the
16
- # universal transverse mercator grid imposed on
17
- # topographic maps by the USA and NATO
18
- # * +:magnetic+ (+:MAG+) - VOR aligned towards magnetic north
11
+ # ===Cheat Sheet in Pseudo Code:
12
+ # vor = AIXM.vor(
13
+ # source: String or nil
14
+ # region: String or nil (falls back to AIXM.config.region)
15
+ # organisation: AIXM.organisation
16
+ # id: String
17
+ # name: String
18
+ # xy: AIXM.xy
19
+ # z: AIXM.z or nil
20
+ # type: TYPES
21
+ # f: AIXM.f
22
+ # north: NORTHS
23
+ # )
24
+ # vor.timetable = AIXM.timetable or nil
25
+ # vor.remarks = String or nil
26
+ # vor.associate_dme(channel: String) # turns the VOR into a VOR/DME
27
+ # vor.associate_tacan(channel: String) # turns the VOR into a VORTAC
19
28
  #
20
- # https://en.wikipedia.org/wiki/VHF_omnidirectional_range
21
- class VOR < Base
22
- using AIXM::Refinements
29
+ # @see https://github.com/openflightmaps/ofmx/wiki/Navigational-aid#vor-vor
30
+ class VOR < NavigationalAid
31
+ public_class_method :new
23
32
 
24
33
  TYPES = {
25
34
  VOR: :conventional,
26
- DVOR: :doppler
35
+ DVOR: :doppler,
36
+ OTHER: :other # specify in remarks
27
37
  }.freeze
28
38
 
29
39
  NORTHS = {
30
40
  TRUE: :geographic,
31
- GRID: :grid,
32
- MAG: :magnetic
41
+ GRID: :grid, # parallel to the north-south lines of the UTM grid
42
+ MAG: :magnetic,
43
+ OTHER: :other # specify in remarks
33
44
  }.freeze
34
45
 
35
- attr_reader :type, :f, :north, :dme, :tacan
46
+ # @return [Symbol] type of VOR (see {TYPES})
47
+ attr_reader :type
36
48
 
37
- public_class_method :new
49
+ # @return [AIXM::F] radio requency
50
+ attr_reader :f
51
+
52
+ # @return [Symbol] north indication (see {NORTHS})
53
+ attr_reader :north
54
+
55
+ # @return [AIXM::Feature::NavigationalAid::DME, nil] associated DME
56
+ attr_reader :dme
57
+
58
+ # @return [AIXM::Feature::NavigationalAid::TACAN, nil] associated TACAN
59
+ attr_reader :tacan
38
60
 
39
- def initialize(id:, name:, xy:, z: nil, type:, f:, north:)
40
- super(id: id, name: name, xy: xy, z: z)
61
+ def initialize(type:, f:, north:, **arguments)
62
+ super(**arguments)
41
63
  self.type, self.f, self.north = type, f, north
42
64
  end
43
65
 
44
66
  def type=(value)
45
- @type = TYPES.lookup(value&.to_sym, nil) || fail(ArgumentError, "invalid type")
46
- end
47
-
48
- def type_key
49
- TYPES.key(type)
67
+ @type = TYPES.lookup(value&.to_s&.to_sym, nil) || fail(ArgumentError, "invalid type")
50
68
  end
51
69
 
52
70
  def f=(value)
@@ -55,55 +73,39 @@ module AIXM
55
73
  end
56
74
 
57
75
  def north=(value)
58
- @north = NORTHS.lookup(value&.to_sym, nil) || fail(ArgumentError, "invalid north")
59
- end
60
-
61
- def north_key
62
- NORTHS.key(north)
76
+ @north = NORTHS.lookup(value&.to_s&.to_sym, nil) || fail(ArgumentError, "invalid north")
63
77
  end
64
78
 
65
- ##
66
- # Associate a DME (also known as VOR/DME)
79
+ # Associate a DME which turns the VOR into a VOR/DME
67
80
  def associate_dme(channel:)
68
- @dme = AIXM.dme(id: id, name: name, xy: xy, z: z, channel: channel)
69
- @dme.schedule = schedule
70
- @dme.remarks = remarks
71
- @dme.vor = self
81
+ @dme = AIXM.dme(organisation: organisation, id: id, name: name, xy: xy, z: z, channel: channel)
82
+ @dme.region, @dme.timetable, @dme.remarks = region, timetable, remarks
83
+ @dme.send(:vor=, self)
72
84
  end
73
85
 
74
- ##
75
- # Associate a TACAN (also known as VORTAC)
86
+ # Associate a TACAN which turns the VOR into a VORTAC
76
87
  def associate_tacan(channel:)
77
- @tacan = AIXM.tacan(id: id, name: name, xy: xy, z: z, channel: channel)
78
- @tacan.schedule = schedule
79
- @tacan.remarks = remarks
80
- @tacan.vor = self
81
- end
82
-
83
- ##
84
- # Digest to identify the payload
85
- def to_digest
86
- [super, type, f.to_digest, north].to_digest
88
+ @tacan = AIXM.tacan(organisation: organisation, id: id, name: name, xy: xy, z: z, channel: channel)
89
+ @tacan.region, @tacan.timetable, @tacan.remarks = region, timetable, remarks
90
+ @tacan.send(:vor=, self)
87
91
  end
88
92
 
89
- ##
90
- # Render UID markup
91
- def to_uid(*extensions)
93
+ # @return [String] UID markup
94
+ def to_uid
92
95
  builder = Builder::XmlMarkup.new(indent: 2)
93
- builder.VorUid({ mid: to_digest, newEntity: (true if extensions >> :ofm) }.compact) do |voruid|
94
- voruid.codeId(id)
95
- voruid.geoLat(xy.lat(format_for(*extensions)))
96
- voruid.geoLong(xy.long(format_for(*extensions)))
96
+ builder.VorUid({ region: (region if AIXM.ofmx?) }.compact) do |vor_uid|
97
+ vor_uid.codeId(id)
98
+ vor_uid.geoLat(xy.lat(AIXM.schema))
99
+ vor_uid.geoLong(xy.long(AIXM.schema))
97
100
  end
98
101
  end
99
102
 
100
- ##
101
- # Render AIXM markup
102
- def to_aixm(*extensions)
103
- builder = to_builder(*extensions)
104
- builder.Vor do |vor|
105
- vor << to_uid(*extensions).indent(2)
106
- vor.OrgUid
103
+ # @return [String] AIXM or OFMX markup
104
+ def to_xml
105
+ builder = to_builder
106
+ builder.Vor({ source: (source if AIXM.ofmx?) }.compact) do |vor|
107
+ vor << to_uid.indent(2)
108
+ vor << organisation.to_uid.indent(2)
107
109
  vor.txtName(name) if name
108
110
  vor.codeType(type_key.to_s)
109
111
  vor.valFreq(f.freq.trim)
@@ -112,18 +114,24 @@ module AIXM
112
114
  vor.codeDatum('WGE')
113
115
  if z
114
116
  vor.valElev(z.alt)
115
- vor.uomDistVer(z.unit.to_s)
116
- end
117
- if schedule
118
- vor.Vtt do |vtt|
119
- vtt << schedule.to_aixm(*extensions).indent(4)
120
- end
117
+ vor.uomDistVer(z.unit.upcase.to_s)
121
118
  end
119
+ vor << timetable.to_xml(as: :Vtt).indent(2) if timetable
122
120
  vor.txtRmk(remarks) if remarks
123
121
  end
124
- builder << @dme.to_aixm(*extensions) if @dme
125
- builder << @tacan.to_aixm(*extensions) if @tacan
126
- builder.target! # see https://github.com/jimweirich/builder/issues/42
122
+ builder << @dme.to_xml if @dme
123
+ builder << @tacan.to_xml if @tacan
124
+ builder.target!
125
+ end
126
+
127
+ # @api private
128
+ def type_key
129
+ TYPES.key(type)
130
+ end
131
+
132
+ # @api private
133
+ def north_key
134
+ NORTHS.key(north)
127
135
  end
128
136
  end
129
137
 
@@ -0,0 +1,97 @@
1
+ using AIXM::Refinements
2
+
3
+ module AIXM
4
+ class Feature
5
+
6
+ # Organisations and authorities such as ATS organisations, aircraft
7
+ # operating agencies, states and so forth.
8
+ #
9
+ # ===Cheat Sheet in Pseudo Code:
10
+ # organisation = AIXM.organisation(
11
+ # source: String or nil
12
+ # region: String or nil (falls back to +AIXM.config.region+)
13
+ # name: String
14
+ # type: TYPES
15
+ # )
16
+ # organisation.id = String or nil
17
+ # organisation.remarks = String or nil
18
+ #
19
+ # @see https://github.com/openflightmaps/ofmx/wiki/Organisation#org-organisation
20
+ class Organisation < Feature
21
+ public_class_method :new
22
+
23
+ TYPES = {
24
+ S: :state,
25
+ GS: :group_of_states,
26
+ O: :national_organisation,
27
+ IO: :international_organisation,
28
+ AOA: :aircraft_operating_agency,
29
+ ATS: :air_traffic_services_provider,
30
+ HA: :handling_authority,
31
+ A: :national_authority,
32
+ OTHER: :other # specify in remarks
33
+ }.freeze
34
+
35
+ # @return [String] name of organisation (e.g. "FRANCE")
36
+ attr_reader :name
37
+
38
+ # @return [Symbol] type of organisation (see {TYPES})
39
+ attr_reader :type
40
+
41
+ # @return [String, nil] code of the organisation (e.g. "LF")
42
+ attr_reader :id
43
+
44
+ # @return [String, nil] free text remarks
45
+ attr_reader :remarks
46
+
47
+ def initialize(source: nil, region: nil, name:, type:)
48
+ super(source: source, region: region)
49
+ self.name, self.type = name, type
50
+ end
51
+
52
+ # @return [String]
53
+ def inspect
54
+ %Q(#<#{self.class} name=#{name.inspect} type=#{type.inspect}>)
55
+ end
56
+
57
+ def name=(value)
58
+ fail(ArgumentError, "invalid name") unless value.is_a? String
59
+ @name = value.uptrans
60
+ end
61
+
62
+ def type=(value)
63
+ @type = TYPES.lookup(value&.to_s&.to_sym, nil) || fail(ArgumentError, "invalid type")
64
+ end
65
+
66
+ def id=(value)
67
+ fail(ArgumentError, "invalid id") unless value.nil? || value.is_a?(String)
68
+ @id = value&.upcase
69
+ end
70
+
71
+ def remarks=(value)
72
+ @remarks = value&.to_s
73
+ end
74
+
75
+ # @return [String] UID markup
76
+ def to_uid
77
+ builder = Builder::XmlMarkup.new(indent: 2)
78
+ builder.OrgUid({ region: (region if AIXM.ofmx?) }.compact) do |org_uid|
79
+ org_uid.txtName(name)
80
+ end
81
+ end
82
+
83
+ # @return [String] AIXM or OFMX markup
84
+ def to_xml
85
+ builder = Builder::XmlMarkup.new(indent: 2)
86
+ builder.comment! "Organisation: #{name}"
87
+ builder.Org({ source: (source if AIXM.ofmx?) }.compact) do |org|
88
+ org << to_uid.indent(2)
89
+ org.codeId(id) if id
90
+ org.codeType(TYPES.key(type).to_s)
91
+ org.txtRmk(remarks) if remarks
92
+ end
93
+ end
94
+ end
95
+
96
+ end
97
+ end
@@ -0,0 +1,152 @@
1
+ using AIXM::Refinements
2
+
3
+ module AIXM
4
+ class Feature
5
+
6
+ # Units providing all kind of services such as air traffic management,
7
+ # search and rescue, meteorological services and so forth.
8
+ #
9
+ # ===Cheat Sheet in Pseudo Code:
10
+ # unit = AIXM.unit(
11
+ # source: String or nil
12
+ # region: String or nil (falls back to +AIXM.config.region+)
13
+ # organisation: AIXM.organisation
14
+ # name: String
15
+ # type: TYPES
16
+ # class: :icao or :other
17
+ # )
18
+ # unit.airport = AIXM.airport or nil
19
+ # unit.remarks = String or nil
20
+ # unit.add_service(AIXM.service)
21
+ #
22
+ # @see https://github.com/openflightmaps/ofmx/wiki/Organisation#uni-unit
23
+ class Unit < Feature
24
+ public_class_method :new
25
+
26
+ TYPES = {
27
+ ACC: :area_control_centre,
28
+ APP: :approach_control_office,
29
+ ARO: :ats_reporting_office,
30
+ ATSU: :air_traffic_services_unit,
31
+ COM: :communications_office,
32
+ FIC: :flight_information_centre,
33
+ FSS: :flight_service_station,
34
+ MET: :meteorological_office,
35
+ NOF: :international_notam_office,
36
+ RAD: :radar_office,
37
+ TWR: :aerodrome_control_tower,
38
+ OTHER: :other # specify in remarks
39
+ }.freeze
40
+
41
+ CLASSES = {
42
+ ICAO: :icao,
43
+ OTHER: :other # specify in remarks
44
+ }.freeze
45
+
46
+ # @return [AIXM::Feature::Organisation] superior organisation
47
+ attr_reader :organisation
48
+
49
+ # @return [String] name of unit (e.g. "MARSEILLE ACS")
50
+ attr_reader :name
51
+
52
+ # @return [Symbol] type of unit (see {TYPES})
53
+ attr_reader :type
54
+
55
+ # @return [AIXM::Feature::Airport, nil] airport
56
+ attr_reader :airport
57
+
58
+ # @return [String, nil] free text remarks
59
+ attr_reader :remarks
60
+
61
+ def initialize(source: nil, region: nil, organisation:, name:, type:, class:)
62
+ super(source: source, region: region)
63
+ self.organisation, self.name, self.type = organisation, name, type
64
+ self.class = binding.local_variable_get(:class)
65
+ @services = []
66
+ end
67
+
68
+ # @return [String]
69
+ def inspect
70
+ %Q(#<#{self.class} name=#{name.inspect} type=#{type.inspect}>)
71
+ end
72
+
73
+ def organisation=(value)
74
+ fail(ArgumentError, "invalid organisation") unless value.is_a? AIXM::Feature::Organisation
75
+ @organisation = value
76
+ end
77
+
78
+ def name=(value)
79
+ fail(ArgumentError, "invalid name") unless value.is_a? String
80
+ @name = value.uptrans
81
+ end
82
+
83
+ def type=(value)
84
+ @type = TYPES.lookup(value&.to_s&.to_sym, nil) || fail(ArgumentError, "invalid type")
85
+ end
86
+
87
+ # @!attribute class
88
+ # @return [Symbol] class of unit (see {CLASSES})
89
+ def class
90
+ @klass
91
+ end
92
+
93
+ def class=(value)
94
+ @klass = CLASSES.lookup(value&.to_s&.to_sym, nil) || fail(ArgumentError, "invalid class")
95
+ end
96
+
97
+ def airport=(value)
98
+ fail(ArgumentError, "invalid airport") unless value.nil? || value.is_a?(AIXM::Feature::Airport)
99
+ @airport = value
100
+ end
101
+
102
+ def remarks=(value)
103
+ @remarks = value&.to_s
104
+ end
105
+
106
+ # Add a service provided by this unit.
107
+ #
108
+ # @param service [AIXM::Component::Service] service instance
109
+ # @return [self]
110
+ def add_service(service)
111
+ fail(ArgumentError, "invalid service") unless service.is_a? AIXM::Component::Service
112
+ service.send(:unit=, self)
113
+ @services << service
114
+ self
115
+ end
116
+
117
+ # @!attribute [r] services
118
+ # @return [Array<AIXM::Component::Service>] services provided by this unit
119
+ def services
120
+ @services.sort { |a, b| [a.type, a.name] <=> [b.type, b.name] }
121
+ end
122
+
123
+ # @return [String] UID markup
124
+ def to_uid
125
+ builder = Builder::XmlMarkup.new(indent: 2)
126
+ builder.UniUid({ region: (region if AIXM.ofmx?) }.compact) do |uni_uid|
127
+ uni_uid.txtName(name)
128
+ end
129
+ end
130
+
131
+ # @return [String] AIXM or OFMX markup
132
+ def to_xml
133
+ builder = Builder::XmlMarkup.new(indent: 2)
134
+ builder.comment! "Unit: #{name}"
135
+ builder.Uni({ source: (source if AIXM.ofmx?) }.compact) do |uni|
136
+ uni << to_uid.indent(2)
137
+ uni << organisation.to_uid.indent(2)
138
+ uni << airport.to_uid.indent(2) if airport
139
+ uni.codeType(TYPES.key(type).to_s)
140
+ uni.codeClass(CLASSES.key(self.class).to_s)
141
+ uni.txtRmk(remarks) if remarks
142
+ end
143
+ services.each.with_object({}) do |service, sequences|
144
+ sequences[service.type] = (sequences[service.type] || 0) + 1
145
+ builder << service.to_xml(sequences[service.type])
146
+ end
147
+ builder.target!
148
+ end
149
+ end
150
+
151
+ end
152
+ end