aixm 0.2.0 → 0.2.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +149 -116
- data/lib/aixm/component/class_layer.rb +3 -3
- data/lib/aixm/component/geometry.rb +3 -3
- data/lib/aixm/component/geometry/arc.rb +2 -2
- data/lib/aixm/component/geometry/border.rb +2 -2
- data/lib/aixm/component/geometry/circle.rb +2 -2
- data/lib/aixm/component/geometry/point.rb +2 -2
- data/lib/aixm/component/schedule.rb +2 -2
- data/lib/aixm/component/vertical_limits.rb +2 -2
- data/lib/aixm/document.rb +4 -4
- data/lib/aixm/feature/airspace.rb +42 -17
- data/lib/aixm/feature/navigational_aid/base.rb +41 -8
- data/lib/aixm/feature/navigational_aid/designated_point.rb +29 -15
- data/lib/aixm/feature/navigational_aid/dme.rb +32 -9
- data/lib/aixm/feature/navigational_aid/marker.rb +25 -7
- data/lib/aixm/feature/navigational_aid/ndb.rb +25 -9
- data/lib/aixm/feature/navigational_aid/tacan.rb +21 -20
- data/lib/aixm/feature/navigational_aid/vor.rb +66 -26
- data/lib/aixm/version.rb +1 -1
- data/spec/factory.rb +69 -13
- data/spec/lib/aixm/component/class_layer_spec.rb +4 -4
- data/spec/lib/aixm/component/geometry/arc_spec.rb +3 -3
- data/spec/lib/aixm/component/geometry/border_spec.rb +2 -2
- data/spec/lib/aixm/component/geometry/circle_spec.rb +3 -3
- data/spec/lib/aixm/component/geometry/point_spec.rb +3 -3
- data/spec/lib/aixm/component/geometry_spec.rb +4 -4
- data/spec/lib/aixm/component/schedule_spec.rb +2 -2
- data/spec/lib/aixm/component/vertical_limits_spec.rb +4 -4
- data/spec/lib/aixm/document_spec.rb +282 -28
- data/spec/lib/aixm/feature/airspace_spec.rb +14 -10
- data/spec/lib/aixm/feature/navigational_aid/designated_point_spec.rb +9 -6
- data/spec/lib/aixm/feature/navigational_aid/dme_spec.rb +9 -6
- data/spec/lib/aixm/feature/navigational_aid/marker_spec.rb +7 -4
- data/spec/lib/aixm/feature/navigational_aid/ndb_spec.rb +9 -6
- data/spec/lib/aixm/feature/navigational_aid/tacan_spec.rb +9 -6
- data/spec/lib/aixm/feature/navigational_aid/vor_spec.rb +156 -7
- metadata +2 -2
@@ -16,8 +16,12 @@ module AIXM
|
|
16
16
|
|
17
17
|
def initialize(id:, name:, xy:, z: nil, f:)
|
18
18
|
super(id: id, name: name, xy: xy, z: z)
|
19
|
-
|
20
|
-
|
19
|
+
self.f = f
|
20
|
+
end
|
21
|
+
|
22
|
+
def f=(value)
|
23
|
+
fail(ArgumentError, "invalid f") unless value.is_a?(F) && value.between?(190, 1750, :khz)
|
24
|
+
@f = value
|
21
25
|
end
|
22
26
|
|
23
27
|
##
|
@@ -27,15 +31,22 @@ module AIXM
|
|
27
31
|
end
|
28
32
|
|
29
33
|
##
|
30
|
-
# Render
|
31
|
-
def
|
34
|
+
# Render UID markup
|
35
|
+
def to_uid(*extensions)
|
36
|
+
builder = Builder::XmlMarkup.new(indent: 2)
|
37
|
+
builder.NdbUid({ newEntity: (true if extensions >> :ofm) }.compact) do |ndbuid|
|
38
|
+
ndbuid.codeId(id)
|
39
|
+
ndbuid.geoLat(xy.lat(format_for(*extensions)))
|
40
|
+
ndbuid.geoLong(xy.long(format_for(*extensions)))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Render AIXM markup
|
46
|
+
def to_aixm(*extensions)
|
32
47
|
builder = to_builder(*extensions)
|
33
48
|
builder.Ndb do |ndb|
|
34
|
-
ndb
|
35
|
-
ndbuid.codeId(id)
|
36
|
-
ndbuid.geoLat(xy.lat(format_for(*extensions)))
|
37
|
-
ndbuid.geoLong(xy.long(format_for(*extensions)))
|
38
|
-
end
|
49
|
+
ndb << to_uid(*extensions).indent(2)
|
39
50
|
ndb.OrgUid
|
40
51
|
ndb.txtName(name)
|
41
52
|
ndb.valFreq(f.freq.trim)
|
@@ -45,6 +56,11 @@ module AIXM
|
|
45
56
|
ndb.valElev(z.alt)
|
46
57
|
ndb.uomDistVer(z.unit.to_s)
|
47
58
|
end
|
59
|
+
if schedule
|
60
|
+
ndb.Ntt do |ntt|
|
61
|
+
ntt << schedule.to_aixm(*extensions).indent(4)
|
62
|
+
end
|
63
|
+
end
|
48
64
|
ndb.txtRmk(remarks) if remarks
|
49
65
|
ndb.target! # see https://github.com/jimweirich/builder/issues/42
|
50
66
|
end
|
@@ -3,39 +3,35 @@ module AIXM
|
|
3
3
|
module NavigationalAid
|
4
4
|
|
5
5
|
##
|
6
|
-
# TACAN (tactical air navigation system)
|
7
|
-
#
|
6
|
+
# TACAN (tactical air navigation system) can be used as a DME by civilian
|
7
|
+
# aircraft and therefore operate in the frequency band between 960 MHz
|
8
|
+
# and 1215 MHz.
|
8
9
|
#
|
9
10
|
# https://en.wikipedia.org/wiki/Tactical_air_navigation_system
|
10
|
-
class TACAN <
|
11
|
+
class TACAN < DME
|
11
12
|
using AIXM::Refinements
|
12
13
|
|
13
|
-
attr_reader :channel
|
14
|
-
|
15
14
|
public_class_method :new
|
16
15
|
|
17
|
-
def initialize(id:, name:, xy:, z: nil, channel:)
|
18
|
-
super(id: id, name: name, xy: xy, z: z)
|
19
|
-
@channel = channel&.upcase
|
20
|
-
end
|
21
|
-
|
22
16
|
##
|
23
|
-
#
|
24
|
-
def
|
25
|
-
|
17
|
+
# Render UID markup
|
18
|
+
def to_uid(*extensions)
|
19
|
+
builder = Builder::XmlMarkup.new(indent: 2)
|
20
|
+
builder.TcnUid({ newEntity: (true if extensions >> :ofm) }.compact) do |tcnuid|
|
21
|
+
tcnuid.codeId(id)
|
22
|
+
tcnuid.geoLat(xy.lat(format_for(*extensions)))
|
23
|
+
tcnuid.geoLong(xy.long(format_for(*extensions)))
|
24
|
+
end
|
26
25
|
end
|
27
26
|
|
28
27
|
##
|
29
|
-
# Render AIXM
|
30
|
-
def
|
28
|
+
# Render AIXM markup
|
29
|
+
def to_aixm(*extensions)
|
31
30
|
builder = to_builder(*extensions)
|
32
31
|
builder.Tcn do |tcn|
|
33
|
-
tcn
|
34
|
-
tcnuid.codeId(id)
|
35
|
-
tcnuid.geoLat(xy.lat(format_for(*extensions)))
|
36
|
-
tcnuid.geoLong(xy.long(format_for(*extensions)))
|
37
|
-
end
|
32
|
+
tcn << to_uid(*extensions).indent(2)
|
38
33
|
tcn.OrgUid
|
34
|
+
tcn << vor.to_uid(*extensions).indent(2) if vor
|
39
35
|
tcn.txtName(name)
|
40
36
|
tcn.codeChannel(channel)
|
41
37
|
tcn.codeDatum('WGE')
|
@@ -43,6 +39,11 @@ module AIXM
|
|
43
39
|
tcn.valElev(z.alt)
|
44
40
|
tcn.uomDistVer(z.unit.to_s)
|
45
41
|
end
|
42
|
+
if schedule
|
43
|
+
tcn.Ttt do |ttt|
|
44
|
+
ttt << schedule.to_aixm(*extensions).indent(4)
|
45
|
+
end
|
46
|
+
end
|
46
47
|
tcn.txtRmk(remarks) if remarks
|
47
48
|
tcn.target! # see https://github.com/jimweirich/builder/issues/42
|
48
49
|
end
|
@@ -8,7 +8,7 @@ module AIXM
|
|
8
8
|
#
|
9
9
|
# Types:
|
10
10
|
# * +:vor+ (+:VOR+) - standard VOR
|
11
|
-
# * +:
|
11
|
+
# * +:doppler_vor+ (+:DVOR+) - Doppler VOR
|
12
12
|
#
|
13
13
|
# North types:
|
14
14
|
# * +:geographic+ (+:TRUE+) - VOR aligned towards geographic north
|
@@ -16,7 +16,6 @@ module AIXM
|
|
16
16
|
# universal transverse mercator grid imposed on
|
17
17
|
# topographic maps by the USA and NATO
|
18
18
|
# * +:magnetic+ (+:MAG+) - VOR aligned towards magnetic north
|
19
|
-
# * +:other+ (+:OTHER+) - other north type
|
20
19
|
#
|
21
20
|
# https://en.wikipedia.org/wiki/VHF_omnidirectional_range
|
22
21
|
class VOR < Base
|
@@ -24,26 +23,61 @@ module AIXM
|
|
24
23
|
|
25
24
|
TYPES = {
|
26
25
|
VOR: :vor,
|
27
|
-
DVOR: :
|
26
|
+
DVOR: :doppler_vor
|
28
27
|
}.freeze
|
29
28
|
|
30
29
|
NORTHS = {
|
31
30
|
TRUE: :geographic,
|
32
31
|
GRID: :grid,
|
33
|
-
MAG: :magnetic
|
34
|
-
OTHER: :other
|
32
|
+
MAG: :magnetic
|
35
33
|
}.freeze
|
36
34
|
|
37
|
-
attr_reader :type, :f, :north
|
35
|
+
attr_reader :type, :f, :north, :dme, :tacan
|
38
36
|
|
39
37
|
public_class_method :new
|
40
38
|
|
41
39
|
def initialize(id:, name:, xy:, z: nil, type:, f:, north:)
|
42
40
|
super(id: id, name: name, xy: xy, z: z)
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
41
|
+
self.type, self.f, self.north = type, f, north
|
42
|
+
end
|
43
|
+
|
44
|
+
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)
|
50
|
+
end
|
51
|
+
|
52
|
+
def f=(value)
|
53
|
+
fail(ArgumentError, "invalid f") unless value.is_a?(F) && value.between?(108, 117.95, :mhz)
|
54
|
+
@f = value
|
55
|
+
end
|
56
|
+
|
57
|
+
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)
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# Associate a DME (also known as VOR/DME)
|
67
|
+
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
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Associate a TACAN (also known as VORTAC)
|
76
|
+
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
|
47
81
|
end
|
48
82
|
|
49
83
|
##
|
@@ -53,15 +87,22 @@ module AIXM
|
|
53
87
|
end
|
54
88
|
|
55
89
|
##
|
56
|
-
# Render
|
57
|
-
def
|
90
|
+
# Render UID markup
|
91
|
+
def to_uid(*extensions)
|
92
|
+
builder = Builder::XmlMarkup.new(indent: 2)
|
93
|
+
builder.VorUid({ 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)))
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
##
|
101
|
+
# Render AIXM markup
|
102
|
+
def to_aixm(*extensions)
|
58
103
|
builder = to_builder(*extensions)
|
59
104
|
builder.Vor do |vor|
|
60
|
-
vor
|
61
|
-
voruid.codeId(id)
|
62
|
-
voruid.geoLat(xy.lat(format_for(*extensions)))
|
63
|
-
voruid.geoLong(xy.long(format_for(*extensions)))
|
64
|
-
end
|
105
|
+
vor << to_uid(*extensions).indent(2)
|
65
106
|
vor.OrgUid
|
66
107
|
vor.txtName(name)
|
67
108
|
vor.codeType(type_key.to_s)
|
@@ -73,17 +114,16 @@ module AIXM
|
|
73
114
|
vor.valElev(z.alt)
|
74
115
|
vor.uomDistVer(z.unit.to_s)
|
75
116
|
end
|
117
|
+
if schedule
|
118
|
+
vor.Vtt do |vtt|
|
119
|
+
vtt << schedule.to_aixm(*extensions).indent(4)
|
120
|
+
end
|
121
|
+
end
|
76
122
|
vor.txtRmk(remarks) if remarks
|
77
|
-
vor.target! # see https://github.com/jimweirich/builder/issues/42
|
78
123
|
end
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
TYPES.key(type)
|
83
|
-
end
|
84
|
-
|
85
|
-
def north_key
|
86
|
-
NORTHS.key(north)
|
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
|
87
127
|
end
|
88
128
|
end
|
89
129
|
|
data/lib/aixm/version.rb
CHANGED
data/spec/factory.rb
CHANGED
@@ -48,26 +48,26 @@ module AIXM
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
def polygon_airspace
|
51
|
+
def polygon_airspace
|
52
52
|
AIXM.airspace(
|
53
53
|
name: 'POLYGON AIRSPACE',
|
54
|
-
short_name:
|
54
|
+
short_name: 'POLYGON',
|
55
55
|
type: 'D'
|
56
56
|
).tap do |airspace|
|
57
|
-
airspace.schedule = AIXM
|
57
|
+
airspace.schedule = AIXM::H24
|
58
58
|
airspace.class_layers << class_layer
|
59
59
|
airspace.geometry = polygon_geometry
|
60
60
|
airspace.remarks = 'polygon airspace'
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
-
def circle_airspace
|
64
|
+
def circle_airspace
|
65
65
|
AIXM.airspace(
|
66
66
|
name: 'CIRCLE AIRSPACE',
|
67
|
-
short_name:
|
67
|
+
short_name: 'CIRCLE',
|
68
68
|
type: 'D'
|
69
69
|
).tap do |airspace|
|
70
|
-
airspace.schedule = AIXM
|
70
|
+
airspace.schedule = AIXM::H24
|
71
71
|
airspace.class_layers << class_layer
|
72
72
|
airspace.geometry = circle_geometry
|
73
73
|
airspace.remarks = 'circle airspace'
|
@@ -76,24 +76,26 @@ module AIXM
|
|
76
76
|
|
77
77
|
def designated_point
|
78
78
|
AIXM.designated_point(
|
79
|
-
id: '
|
79
|
+
id: 'DDD',
|
80
80
|
name: 'DESIGNATED POINT NAVAID',
|
81
81
|
xy: AIXM.xy(lat: %q(47°51'33"N), long: %q(007°33'36"E)),
|
82
82
|
z: AIXM.z(500, :qnh),
|
83
83
|
type: :ICAO
|
84
84
|
).tap do |designated_point|
|
85
|
+
designated_point.schedule = AIXM::H24
|
85
86
|
designated_point.remarks = 'designated point navaid'
|
86
87
|
end
|
87
88
|
end
|
88
89
|
|
89
90
|
def dme
|
90
91
|
AIXM.dme(
|
91
|
-
id: '
|
92
|
+
id: 'MMM',
|
92
93
|
name: 'DME NAVAID',
|
93
94
|
xy: AIXM.xy(lat: %q(47°51'33"N), long: %q(007°33'36"E)),
|
94
95
|
z: AIXM.z(500, :qnh),
|
95
96
|
channel: '95X'
|
96
97
|
).tap do |dme|
|
98
|
+
dme.schedule = AIXM::H24
|
97
99
|
dme.remarks = 'dme navaid'
|
98
100
|
end
|
99
101
|
end
|
@@ -105,48 +107,99 @@ module AIXM
|
|
105
107
|
xy: AIXM.xy(lat: %q(47°51'33"N), long: %q(007°33'36"E)),
|
106
108
|
z: AIXM.z(500, :qnh)
|
107
109
|
).tap do |marker|
|
110
|
+
marker.schedule = AIXM::H24
|
108
111
|
marker.remarks = 'marker navaid'
|
109
112
|
end
|
110
113
|
end
|
111
114
|
|
112
115
|
def ndb
|
113
116
|
AIXM.ndb(
|
114
|
-
id: '
|
117
|
+
id: 'NNN',
|
115
118
|
name: 'NDB NAVAID',
|
116
119
|
xy: AIXM.xy(lat: %q(47°51'33"N), long: %q(007°33'36"E)),
|
117
120
|
z: AIXM.z(500, :qnh),
|
118
121
|
f: AIXM.f(555, :khz)
|
119
122
|
).tap do |ndb|
|
123
|
+
ndb.schedule = AIXM::H24
|
120
124
|
ndb.remarks = 'ndb navaid'
|
121
125
|
end
|
122
126
|
end
|
123
127
|
|
124
128
|
def tacan
|
125
129
|
AIXM.tacan(
|
126
|
-
id: '
|
130
|
+
id: 'TTT',
|
127
131
|
name: 'TACAN NAVAID',
|
128
132
|
xy: AIXM.xy(lat: %q(47°51'33"N), long: %q(007°33'36"E)),
|
129
133
|
z: AIXM.z(500, :qnh),
|
130
134
|
channel: '29X'
|
131
135
|
).tap do |tacan|
|
136
|
+
tacan.schedule = AIXM::H24
|
132
137
|
tacan.remarks = 'tacan navaid'
|
133
138
|
end
|
134
139
|
end
|
135
140
|
|
136
141
|
def vor
|
137
142
|
AIXM.vor(
|
138
|
-
id: '
|
143
|
+
id: 'VVV',
|
139
144
|
name: 'VOR NAVAID',
|
140
145
|
xy: AIXM.xy(lat: %q(47°51'33"N), long: %q(007°33'36"E)),
|
141
146
|
z: AIXM.z(500, :qnh),
|
142
|
-
type: :
|
147
|
+
type: :vor,
|
143
148
|
f: AIXM.f(111, :mhz),
|
144
149
|
north: :geographic
|
145
150
|
).tap do |vor|
|
151
|
+
vor.schedule = AIXM::H24
|
146
152
|
vor.remarks = 'vor navaid'
|
147
153
|
end
|
148
154
|
end
|
149
155
|
|
156
|
+
def dvor
|
157
|
+
AIXM.vor(
|
158
|
+
id: 'DVV',
|
159
|
+
name: 'DOPPLER-VOR NAVAID',
|
160
|
+
xy: AIXM.xy(lat: %q(47°51'33"N), long: %q(007°33'36"E)),
|
161
|
+
z: AIXM.z(500, :qnh),
|
162
|
+
type: :doppler_vor,
|
163
|
+
f: AIXM.f(111, :mhz),
|
164
|
+
north: :geographic
|
165
|
+
).tap do |doppler_vor|
|
166
|
+
doppler_vor.schedule = AIXM::H24
|
167
|
+
doppler_vor.remarks = 'doppler-vor navaid'
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def vordme
|
172
|
+
AIXM.vor(
|
173
|
+
id: 'VDD',
|
174
|
+
name: 'VOR/DME NAVAID',
|
175
|
+
xy: AIXM.xy(lat: %q(47°51'33"N), long: %q(007°33'36"E)),
|
176
|
+
z: AIXM.z(500, :qnh),
|
177
|
+
type: :vor,
|
178
|
+
f: AIXM.f(111, :mhz),
|
179
|
+
north: :geographic
|
180
|
+
).tap do |vordme|
|
181
|
+
vordme.schedule = AIXM::H24
|
182
|
+
vordme.remarks = 'vor/dme navaid'
|
183
|
+
vordme.associate_dme(channel: '95X')
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def vortac
|
188
|
+
AIXM.vor(
|
189
|
+
id: 'VTT',
|
190
|
+
name: 'VORTAC NAVAID',
|
191
|
+
xy: AIXM.xy(lat: %q(47°51'33"N), long: %q(007°33'36"E)),
|
192
|
+
z: AIXM.z(500, :qnh),
|
193
|
+
type: :vor,
|
194
|
+
f: AIXM.f(111, :mhz),
|
195
|
+
north: :geographic
|
196
|
+
).tap do |vortac|
|
197
|
+
vortac.schedule = AIXM::H24
|
198
|
+
vortac.remarks = 'vortac navaid'
|
199
|
+
vortac.associate_tacan(channel: '29X')
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
150
203
|
def document
|
151
204
|
time = Time.parse('2018-01-18 12:00:00 +0100')
|
152
205
|
AIXM.document(created_at: time, effective_at: time).tap do |document|
|
@@ -156,8 +209,11 @@ module AIXM
|
|
156
209
|
document.features << AIXM::Factory.dme
|
157
210
|
document.features << AIXM::Factory.marker
|
158
211
|
document.features << AIXM::Factory.ndb
|
159
|
-
document.features << AIXM::Factory.vor
|
160
212
|
document.features << AIXM::Factory.tacan
|
213
|
+
document.features << AIXM::Factory.vor
|
214
|
+
document.features << AIXM::Factory.dvor
|
215
|
+
document.features << AIXM::Factory.vordme
|
216
|
+
document.features << AIXM::Factory.vortac
|
161
217
|
end
|
162
218
|
end
|
163
219
|
|