aixm 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|