aixm 0.3.4 → 0.3.5
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/.travis.yml +1 -1
- data/CHANGELOG.md +11 -0
- data/lib/aixm/component/geometry.rb +4 -2
- data/lib/aixm/component/geometry/arc.rb +1 -1
- data/lib/aixm/component/geometry/border.rb +1 -1
- data/lib/aixm/component/geometry/circle.rb +1 -1
- data/lib/aixm/component/geometry/point.rb +1 -1
- data/lib/aixm/component/layer.rb +6 -2
- data/lib/aixm/component/vertical_limits.rb +17 -14
- data/lib/aixm/constants.rb +1 -1
- data/lib/aixm/feature/address.rb +1 -1
- data/lib/aixm/feature/airspace.rb +1 -3
- data/lib/aixm/feature/obstacle.rb +89 -71
- data/lib/aixm/feature/obstacle_group.rb +71 -30
- data/lib/aixm/refinements.rb +15 -0
- data/lib/aixm/version.rb +1 -1
- data/lib/aixm/xy.rb +5 -0
- data/schemas/ofmx/0/OFMX-DataTypes.xsd +3 -1
- data/schemas/ofmx/0/OFMX-Features.xsd +79 -34
- data/schemas/ofmx/0/OFMX-Snapshot.xsd +1 -0
- data/spec/factory.rb +7 -9
- data/spec/lib/aixm/component/vertical_limits_spec.rb +8 -8
- data/spec/lib/aixm/document_spec.rb +81 -28
- data/spec/lib/aixm/feature/obstacle_group_spec.rb +87 -45
- data/spec/lib/aixm/feature/obstacle_spec.rb +34 -40
- data/spec/lib/aixm/refinements_spec.rb +16 -0
- data/spec/lib/aixm/xy_spec.rb +10 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: efe8ab0dda077e481484589c0e2943b6417cefb5386e16d872692161b46add3f
|
4
|
+
data.tar.gz: f7fb02c428760481b9159d81c93baec8e4e2d1ef1267e1884f02422d44af7b9b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1dcee1f3e19c58ada30b66bfa48201bae02a382bb6a8746b6f144de6c3280ef58ce2e6b6dc25ba5343ff9cfc9589e81e2217573bdfce642623f73530bf626e56
|
7
|
+
data.tar.gz: 1cf3f783adfa14e2af626d97810c8bfbd3e776718a207e70343ed1bf1f2f5ccbaa52142aa5ab32727af99a8c07733d056817536f3157b171878c0d03b9363208
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
## 0.3.5
|
2
|
+
|
3
|
+
#### Additions
|
4
|
+
* Refinement `Object#then_if`
|
5
|
+
* Airspace activity types `:aeromodelling` and `:glider_winch`
|
6
|
+
* `AIXM::XY#to_point` convenience method
|
7
|
+
|
8
|
+
#### Breaking Changes
|
9
|
+
* Renamed airspace activity type "TOWING" from `:winch_activity` to `:towing_traffic`
|
10
|
+
* Updated obstacles and obstacle groups to reflect recent changes in OFMX
|
11
|
+
|
1
12
|
## 0.3.4
|
2
13
|
|
3
14
|
#### Additions
|
@@ -26,7 +26,7 @@ module AIXM
|
|
26
26
|
# @example Built by adding elements
|
27
27
|
# geometry = AIXM.geometry
|
28
28
|
# geometry << AIXM.point(...)
|
29
|
-
# geometry
|
29
|
+
# geometry.concat [AIXM.point(...), AIXM.point(...), ...]
|
30
30
|
#
|
31
31
|
# @see https://github.com/openflightmaps/ofmx/wiki/Airspace#avx-border-vertex
|
32
32
|
class Geometry
|
@@ -37,7 +37,9 @@ module AIXM
|
|
37
37
|
# @return [Enumerator] see Array#each
|
38
38
|
# @!method <<
|
39
39
|
# @return [Array] see Array#<<
|
40
|
-
|
40
|
+
# @!method concat
|
41
|
+
# @return [Array] see Array#concat
|
42
|
+
def_delegators :@result_array, :each, :<<, :concat
|
41
43
|
|
42
44
|
def initialize(*segments)
|
43
45
|
@result_array = segments
|
data/lib/aixm/component/layer.rb
CHANGED
@@ -25,6 +25,7 @@ module AIXM
|
|
25
25
|
ACCIDENT: :accident_investigation,
|
26
26
|
ACROBAT: :acrobatics,
|
27
27
|
AIRGUN: :aerial_gunnery,
|
28
|
+
AIRMODEL: :aeromodelling,
|
28
29
|
AIRSHOW: :air_show,
|
29
30
|
ANTIHAIL: :anti_hail_rocket,
|
30
31
|
ARTILERY: :artillary_firing,
|
@@ -71,7 +72,7 @@ module AIXM
|
|
71
72
|
TECHNICAL: :technical_activity,
|
72
73
|
'TFC-AD': :aerodrome_traffic,
|
73
74
|
'TFC-HELI': :helicopter_traffic,
|
74
|
-
TOWING: :
|
75
|
+
TOWING: :towing_traffic,
|
75
76
|
TRG: :training,
|
76
77
|
UAV: :drone,
|
77
78
|
ULM: :ultra_light_flight,
|
@@ -79,6 +80,7 @@ module AIXM
|
|
79
80
|
'VIP-PRES': :president,
|
80
81
|
'VIP-VICE': :vice_president,
|
81
82
|
WATERBLAST: :underwater_explosion,
|
83
|
+
WINCH: :glider_winch,
|
82
84
|
WORK: :aerial_work,
|
83
85
|
OTHER: :other
|
84
86
|
}.freeze
|
@@ -161,7 +163,9 @@ module AIXM
|
|
161
163
|
builder = Builder::XmlMarkup.new(indent: 2)
|
162
164
|
builder.codeClass(self.class.to_s) if self.class
|
163
165
|
builder.codeLocInd(location_indicator) if location_indicator
|
164
|
-
|
166
|
+
if activity
|
167
|
+
builder.codeActivity(ACTIVITIES.key(activity).to_s.then_if(AIXM.aixm?) { |a| { 'AIRMODEL' => 'UAV', 'WINCH' => 'GLIDER' }[a] || a })
|
168
|
+
end
|
165
169
|
builder << vertical_limits.to_xml
|
166
170
|
builder << timetable.to_xml(as: :Att) if timetable
|
167
171
|
builder.codeSelAvbl(selective? ? 'Y' : 'N') if AIXM.ofmx?
|
@@ -6,15 +6,17 @@ module AIXM
|
|
6
6
|
# Vertical limits define a 3D airspace vertically. They are often noted in
|
7
7
|
# AIP as follows:
|
8
8
|
#
|
9
|
-
# upper_z
|
9
|
+
# upper_z
|
10
|
+
# (max_z) whichever is higher
|
10
11
|
# -------
|
11
|
-
# lower_z
|
12
|
+
# lower_z
|
13
|
+
# (min_z) whichever is lower
|
12
14
|
#
|
13
15
|
# ===Cheat Sheet in Pseudo Code:
|
14
16
|
# vertical_limits = AIXM.vertical_limits(
|
15
17
|
# upper_z: AIXM.z
|
16
|
-
# lower_z: AIXM.z
|
17
18
|
# max_z: AIXM.z or nil
|
19
|
+
# lower_z: AIXM.z
|
18
20
|
# min_z: AIXM.z or nil
|
19
21
|
# )
|
20
22
|
#
|
@@ -25,7 +27,7 @@ module AIXM
|
|
25
27
|
# @see https://github.com/openflightmaps/ofmx/wiki/Airspace#ase-airspace
|
26
28
|
class VerticalLimits
|
27
29
|
# @api private
|
28
|
-
TAGS = {
|
30
|
+
TAGS = { upper_z: :Upper, lower_z: :Lower, max_z: :Max, min_z: :Mnm }.freeze
|
29
31
|
|
30
32
|
# @api private
|
31
33
|
CODES = { qfe: :HEI, qnh: :ALT, qne: :STD }.freeze
|
@@ -42,13 +44,14 @@ module AIXM
|
|
42
44
|
# @return [AIXM::Z] alternative lower limit ("whichever is lower")
|
43
45
|
attr_reader :min_z
|
44
46
|
|
45
|
-
def initialize(upper_z:,
|
46
|
-
self.upper_z, self.
|
47
|
+
def initialize(upper_z:, max_z: nil, lower_z:, min_z: nil)
|
48
|
+
self.upper_z, self.max_z, self.lower_z, self.min_z = upper_z, max_z, lower_z, min_z
|
47
49
|
end
|
48
50
|
|
49
51
|
# @return [String]
|
50
52
|
def inspect
|
51
|
-
%
|
53
|
+
payload = %i(upper_z max_z lower_z min_z).map { |l| %Q(#{l}="#{send(l)}") if send(l) }.compact
|
54
|
+
%Q(#<#{self.class} #{payload.join(' ')}>)
|
52
55
|
end
|
53
56
|
|
54
57
|
def upper_z=(value)
|
@@ -56,16 +59,16 @@ module AIXM
|
|
56
59
|
@upper_z = value
|
57
60
|
end
|
58
61
|
|
59
|
-
def lower_z=(value)
|
60
|
-
fail(ArgumentError, "invalid lower_z") unless value.is_a? AIXM::Z
|
61
|
-
@lower_z = value
|
62
|
-
end
|
63
|
-
|
64
62
|
def max_z=(value)
|
65
63
|
fail(ArgumentError, "invalid max_z") unless value.nil? || value.is_a?(AIXM::Z)
|
66
64
|
@max_z = value
|
67
65
|
end
|
68
66
|
|
67
|
+
def lower_z=(value)
|
68
|
+
fail(ArgumentError, "invalid lower_z") unless value.is_a? AIXM::Z
|
69
|
+
@lower_z = value
|
70
|
+
end
|
71
|
+
|
69
72
|
def min_z=(value)
|
70
73
|
fail(ArgumentError, "invalid min_z") unless value.nil? || value.is_a?(AIXM::Z)
|
71
74
|
@min_z = value
|
@@ -73,8 +76,8 @@ module AIXM
|
|
73
76
|
|
74
77
|
# @return [String] AIXM or OFMX markup
|
75
78
|
def to_xml
|
76
|
-
|
77
|
-
if z = send(
|
79
|
+
TAGS.keys.each_with_object(Builder::XmlMarkup.new(indent: 2)) do |limit, builder|
|
80
|
+
if z = send(limit)
|
78
81
|
builder.tag!(:"codeDistVer#{TAGS[limit]}", CODES[z.code].to_s)
|
79
82
|
builder.tag!(:"valDistVer#{TAGS[limit]}", z.alt.to_s)
|
80
83
|
builder.tag!(:"uomDistVer#{TAGS[limit]}", z.unit.upcase.to_s)
|
data/lib/aixm/constants.rb
CHANGED
data/lib/aixm/feature/address.rb
CHANGED
@@ -79,7 +79,7 @@ module AIXM
|
|
79
79
|
builder = Builder::XmlMarkup.new(indent: 2)
|
80
80
|
builder.tag!(as) do |tag|
|
81
81
|
tag << addressable.to_uid.indent(2) if addressable
|
82
|
-
tag.codeType(TYPES.key(type).to_s.
|
82
|
+
tag.codeType(TYPES.key(type).to_s.then_if(AIXM.aixm?) { |t| t.sub(/-\w+$/, '') })
|
83
83
|
tag.noSeq(sequence)
|
84
84
|
end
|
85
85
|
end
|
@@ -140,9 +140,7 @@ module AIXM
|
|
140
140
|
fail(LayerError.new("no layers defined", self)) unless layers.any?
|
141
141
|
builder = Builder::XmlMarkup.new(indent: 2)
|
142
142
|
builder.comment! "Airspace: [#{TYPES.key(type)}] #{name || :UNNAMED}"
|
143
|
-
builder.Ase({
|
144
|
-
source: (source if AIXM.ofmx?)
|
145
|
-
}.compact) do |ase|
|
143
|
+
builder.Ase({ source: (source if AIXM.ofmx?) }.compact) do |ase|
|
146
144
|
ase << to_uid.indent(2)
|
147
145
|
ase.txtLocalType(local_type) if local_type && local_type != name
|
148
146
|
ase.txtName(name) if name
|
@@ -12,20 +12,29 @@ module AIXM
|
|
12
12
|
# name: String or nil
|
13
13
|
# type: TYPES
|
14
14
|
# xy: AIXM.xy
|
15
|
-
# radius: AIXM.d
|
16
15
|
# z: AIXM.z
|
16
|
+
# radius: AIXM.d
|
17
17
|
# )
|
18
18
|
# obstacle.lighting = true or false (default for AIXM) or nil (means: unknown, default for OFMX)
|
19
19
|
# obstacle.lighting_remarks = String or nil
|
20
20
|
# obstacle.marking = true or false or nil (means: unknown, default)
|
21
21
|
# obstacle.marking_remarks = String or nil
|
22
22
|
# obstacle.height = AIXM.d or nil
|
23
|
+
# obstacle.height_accurate = true or false or nil (means: unknown, default)
|
23
24
|
# obstacle.xy_accuracy = AIXM.d or nil
|
24
25
|
# obstacle.z_accuracy = AIXM.d or nil
|
25
|
-
# obstacle.height_accurate = true or false or nil (means: unknown, default)
|
26
26
|
# obstacle.valid_from = Time or Date or String or nil
|
27
27
|
# obstacle.valid_until = Time or Date or String or nil
|
28
28
|
# obstacle.remarks = String or nil
|
29
|
+
# obstacle.link_to # => AIXM.obstacle or nil
|
30
|
+
# obstacle.link_type # => LINK_TYPE or nil
|
31
|
+
#
|
32
|
+
# See {AIXM::Feature::ObstacleGroup} for how to define physical links
|
33
|
+
# between two obstacles (e.g. cables between powerline towers).
|
34
|
+
#
|
35
|
+
# Please note: As soon as an obstacle is added to an obstacle group, the
|
36
|
+
# +xy_accuracy+ and +z_accuracy+ of the obstacle group overwrite whatever
|
37
|
+
# is set on the individual obstacles!
|
29
38
|
#
|
30
39
|
# @see https://github.com/openflightmaps/ofmx/wiki/Obstacle
|
31
40
|
class Obstacle < Feature
|
@@ -42,6 +51,12 @@ module AIXM
|
|
42
51
|
OTHER: :other # specify in remarks
|
43
52
|
}.freeze
|
44
53
|
|
54
|
+
LINK_TYPES = {
|
55
|
+
CABLE: :cable,
|
56
|
+
SOLID: :solid,
|
57
|
+
OTHER: :other
|
58
|
+
}.freeze
|
59
|
+
|
45
60
|
# @return [String] full name
|
46
61
|
attr_reader :name
|
47
62
|
|
@@ -74,16 +89,16 @@ module AIXM
|
|
74
89
|
# @return [AIXM::D, nil] height from ground to top point
|
75
90
|
attr_reader :height
|
76
91
|
|
92
|
+
# @return [Boolean, nil] height accuracy
|
93
|
+
# true => height measured, false => height estimated, nil => unknown
|
94
|
+
attr_reader :height_accurate
|
95
|
+
|
77
96
|
# @return [AIXM::D, nil] margin of error for circular base center point
|
78
97
|
attr_reader :xy_accuracy
|
79
98
|
|
80
99
|
# @return [AIXM::D, nil] margin of error for top point
|
81
100
|
attr_reader :z_accuracy
|
82
101
|
|
83
|
-
# @return [Boolean, nil] height accuracy
|
84
|
-
# true => height measured, false => height estimated, nil => unknown
|
85
|
-
attr_reader :height_accurate
|
86
|
-
|
87
102
|
# @return [Time, Date, String, nil] effective after this point in time
|
88
103
|
attr_reader :valid_from
|
89
104
|
|
@@ -93,9 +108,18 @@ module AIXM
|
|
93
108
|
# @return [String, nil] free text remarks
|
94
109
|
attr_reader :remarks
|
95
110
|
|
96
|
-
|
111
|
+
# @return [AIXM::Feature::ObstacleGroup] group this obstacle belongs to
|
112
|
+
attr_reader :obstacle_group
|
113
|
+
|
114
|
+
# @return [Symbol, nil] another obstacle to which a physical link exists
|
115
|
+
attr_reader :linked_to
|
116
|
+
|
117
|
+
# @return [Symbol, nil] type of physical link between this and another obstacle
|
118
|
+
attr_reader :link_type
|
119
|
+
|
120
|
+
def initialize(source: nil, name: nil, type:, xy:, z:, radius:)
|
97
121
|
super(source: source)
|
98
|
-
self.name, self.type, self.xy, self.
|
122
|
+
self.name, self.type, self.xy, self.z, self.radius = name, type, xy, z, radius
|
99
123
|
@lighting = @marking = @height_accurate = false
|
100
124
|
end
|
101
125
|
|
@@ -118,16 +142,16 @@ module AIXM
|
|
118
142
|
@xy = value
|
119
143
|
end
|
120
144
|
|
121
|
-
def radius=(value)
|
122
|
-
fail(ArgumentError, "invalid radius") unless value.is_a?(AIXM::D) && value.dist > 0
|
123
|
-
@radius = value
|
124
|
-
end
|
125
|
-
|
126
145
|
def z=(value)
|
127
146
|
fail(ArgumentError, "invalid z") unless value.is_a?(AIXM::Z) && value.qnh?
|
128
147
|
@z = value
|
129
148
|
end
|
130
149
|
|
150
|
+
def radius=(value)
|
151
|
+
fail(ArgumentError, "invalid radius") unless value.nil? || (value.is_a?(AIXM::D) && value.dist > 0)
|
152
|
+
@radius = value
|
153
|
+
end
|
154
|
+
|
131
155
|
def lighting=(value)
|
132
156
|
fail(ArgumentError, "invalid lighting") unless [true, false, nil].include? value
|
133
157
|
@lighting = value
|
@@ -151,6 +175,11 @@ module AIXM
|
|
151
175
|
@height = value
|
152
176
|
end
|
153
177
|
|
178
|
+
def height_accurate=(value)
|
179
|
+
fail(ArgumentError, "invalid height accurate") unless [true, false, nil].include? value
|
180
|
+
@height_accurate = value
|
181
|
+
end
|
182
|
+
|
154
183
|
def xy_accuracy=(value)
|
155
184
|
fail(ArgumentError, "invalid xy accuracy") unless value.nil? || value.is_a?(AIXM::D)
|
156
185
|
@xy_accuracy = value
|
@@ -161,11 +190,6 @@ module AIXM
|
|
161
190
|
@z_accuracy = value
|
162
191
|
end
|
163
192
|
|
164
|
-
def height_accurate=(value)
|
165
|
-
fail(ArgumentError, "invalid height accurate") unless [true, false, nil].include? value
|
166
|
-
@height_accurate = value
|
167
|
-
end
|
168
|
-
|
169
193
|
def valid_from=(value)
|
170
194
|
@valid_from = value&.to_time
|
171
195
|
end
|
@@ -178,39 +202,59 @@ module AIXM
|
|
178
202
|
@remarks = value&.to_s
|
179
203
|
end
|
180
204
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
205
|
+
def obstacle_group=(value)
|
206
|
+
fail(ArgumentError, "invalid obstacle group") unless value.is_a?(AIXM::Feature::ObstacleGroup)
|
207
|
+
@obstacle_group = value
|
208
|
+
end
|
209
|
+
private :obstacle_group=
|
210
|
+
|
211
|
+
def linked_to=(value)
|
212
|
+
fail(ArgumentError, "invalid linked to") unless value.is_a?(AIXM::Feature::Obstacle)
|
213
|
+
@linked_to = value
|
185
214
|
end
|
215
|
+
private :linked_to=
|
216
|
+
|
217
|
+
def link_type=(value)
|
218
|
+
@link_type = LINK_TYPES.lookup(value&.to_s&.to_sym, nil) || fail(ArgumentError, "invalid link type")
|
219
|
+
end
|
220
|
+
private :link_type=
|
186
221
|
|
187
222
|
# @return [Boolean] whether part of an obstacle group
|
188
223
|
def grouped?
|
189
|
-
|
224
|
+
obstacle_group && obstacle_group.obstacles.count > 1
|
225
|
+
end
|
226
|
+
|
227
|
+
# @return [Boolean] whether obstacle is linked to another one
|
228
|
+
def linked?
|
229
|
+
!!linked_to
|
190
230
|
end
|
191
231
|
|
192
232
|
# @return [String] UID markup
|
193
233
|
def to_uid(as: :ObsUid)
|
234
|
+
self.obstacle_group ||= singleton_obstacle_group
|
194
235
|
builder = Builder::XmlMarkup.new(indent: 2)
|
195
236
|
builder.tag!(as) do |tag|
|
237
|
+
tag << obstacle_group.to_uid.indent(2) if AIXM.ofmx?
|
196
238
|
tag.geoLat((xy.lat(AIXM.schema)))
|
197
239
|
tag.geoLong((xy.long(AIXM.schema)))
|
198
240
|
end
|
199
241
|
end
|
200
242
|
|
201
243
|
# @return [String] AIXM or OFMX markup
|
202
|
-
def to_xml
|
244
|
+
def to_xml(delegate: true)
|
245
|
+
self.obstacle_group ||= singleton_obstacle_group
|
246
|
+
return obstacle_group.to_xml if delegate && AIXM.ofmx?
|
203
247
|
builder = Builder::XmlMarkup.new(indent: 2)
|
204
248
|
builder.comment! "Obstacle: [#{type}] #{xy.to_s} #{name}".strip
|
205
|
-
builder.Obs
|
249
|
+
builder.Obs do |obs|
|
206
250
|
obs << to_uid.indent(2)
|
207
251
|
obs.txtName(name) if name
|
208
252
|
if AIXM.ofmx?
|
209
253
|
obs.codeType(TYPES.key(type).to_s)
|
210
254
|
else
|
211
255
|
obs.txtDescrType(TYPES.key(type).to_s)
|
212
|
-
obs.codeGroup(grouped? || clustered? ? 'Y' : 'N')
|
213
256
|
end
|
257
|
+
obs.codeGroup(grouped? ? 'Y' : 'N')
|
214
258
|
if AIXM.ofmx?
|
215
259
|
obs.codeLgt(lighting ? 'Y' : 'N') unless lighting.nil?
|
216
260
|
obs.codeMarking(marking ? 'Y' : 'N') unless marking.nil?
|
@@ -220,27 +264,27 @@ module AIXM
|
|
220
264
|
obs.txtDescrLgt(lighting_remarks) if lighting_remarks
|
221
265
|
obs.txtDescrMarking(marking_remarks) if marking_remarks
|
222
266
|
obs.codeDatum('WGE')
|
223
|
-
if xy_accuracy
|
224
|
-
obs.valGeoAccuracy(xy_accuracy.dist.trim)
|
225
|
-
obs.uomGeoAccuracy(xy_accuracy.unit.upcase.to_s)
|
267
|
+
if AIXM.aixm? && obstacle_group.xy_accuracy
|
268
|
+
obs.valGeoAccuracy(obstacle_group.xy_accuracy.dist.trim)
|
269
|
+
obs.uomGeoAccuracy(obstacle_group.xy_accuracy.unit.upcase.to_s)
|
226
270
|
end
|
227
271
|
obs.valElev(z.alt)
|
228
|
-
|
272
|
+
if AIXM.aixm? && obstacle_group.z_accuracy
|
273
|
+
obs.valElevAccuracy(obstacle_group.z_accuracy.to_ft.dist.round)
|
274
|
+
end
|
229
275
|
obs.valHgt(height.to_ft.dist.round) if height
|
276
|
+
obs.uomDistVer('FT')
|
230
277
|
if AIXM.ofmx? && !height_accurate.nil?
|
231
278
|
obs.codeHgtAccuracy(height_accurate ? 'Y' : 'N')
|
232
279
|
end
|
233
|
-
obs.uomDistVer('FT')
|
234
280
|
if AIXM.ofmx?
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
obs.codeLinkType(AIXM::Feature::ObstacleGroup::LINK_TYPES.key(link_type).to_s)
|
243
|
-
end
|
281
|
+
if radius
|
282
|
+
obs.valRadius(radius.dist.trim)
|
283
|
+
obs.uomRadius(radius.unit.upcase.to_s)
|
284
|
+
end
|
285
|
+
if grouped? && linked?
|
286
|
+
obs << linked_to.to_uid(as: :ObsUidLink).indent(2)
|
287
|
+
obs.codeLinkType(LINK_TYPES.key(link_type).to_s)
|
244
288
|
end
|
245
289
|
obs.datetimeValidWef(valid_from.xmlschema) if valid_from
|
246
290
|
obs.datetimeValidTil(valid_until.xmlschema) if valid_until
|
@@ -249,38 +293,12 @@ module AIXM
|
|
249
293
|
end
|
250
294
|
end
|
251
295
|
|
252
|
-
|
253
|
-
module Grouped
|
254
|
-
# @return [AIXM::Feature::ObstacleGroup] group this obstacle belongs to
|
255
|
-
attr_reader :group
|
256
|
-
|
257
|
-
# @return [AIXM::Feature::Obstacle] another obstacle this one is linked to
|
258
|
-
attr_reader :linked_to
|
259
|
-
|
260
|
-
# @return [Symbol] type of link between two obstacles
|
261
|
-
attr_reader :link_type
|
296
|
+
private
|
262
297
|
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
private :group=
|
268
|
-
|
269
|
-
# @return [Boolean] whether obstacle is linked to another one
|
270
|
-
def linked?
|
271
|
-
!!linked_to
|
272
|
-
end
|
273
|
-
|
274
|
-
def linked_to=(value)
|
275
|
-
fail(ArgumentError, "invalid linked to") unless value.is_a?(AIXM::Feature::Obstacle)
|
276
|
-
@linked_to = value
|
277
|
-
end
|
278
|
-
private :linked_to=
|
279
|
-
|
280
|
-
def link_type=(value)
|
281
|
-
@link_type = AIXM::Feature::ObstacleGroup::LINK_TYPES.lookup(value&.to_s&.to_sym, nil) || fail(ArgumentError, "invalid link type")
|
282
|
-
end
|
283
|
-
private :link_type=
|
298
|
+
# OFMX requires single, ungrouped obstacles to be the only member of a
|
299
|
+
# singleton obstacle group.
|
300
|
+
def singleton_obstacle_group
|
301
|
+
AIXM.obstacle_group.add_obstacle self
|
284
302
|
end
|
285
303
|
|
286
304
|
end
|