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