aixm 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +43 -13
- data/README.md +31 -20
- data/lib/aixm/a.rb +89 -71
- data/lib/aixm/association.rb +37 -27
- data/lib/aixm/classes.rb +5 -2
- data/lib/aixm/{feature → component}/address.rb +12 -9
- data/lib/aixm/component/approach_lighting.rb +136 -0
- data/lib/aixm/component/fato.rb +58 -42
- data/lib/aixm/component/frequency.rb +2 -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 +3 -3
- data/lib/aixm/component/geometry/point.rb +1 -1
- data/lib/aixm/component/geometry/rhumb_line.rb +1 -1
- data/lib/aixm/component/geometry.rb +3 -2
- data/lib/aixm/component/helipad.rb +26 -36
- data/lib/aixm/component/layer.rb +5 -3
- data/lib/aixm/component/lighting.rb +5 -5
- data/lib/aixm/component/runway.rb +81 -52
- data/lib/aixm/component/service.rb +12 -3
- data/lib/aixm/component/surface.rb +12 -12
- data/lib/aixm/component/timetable.rb +2 -2
- data/lib/aixm/component/vasis.rb +105 -0
- data/lib/aixm/component/vertical_limit.rb +3 -3
- data/lib/aixm/component.rb +10 -0
- data/lib/aixm/config.rb +2 -0
- data/lib/aixm/d.rb +16 -15
- data/lib/aixm/document.rb +10 -1
- data/lib/aixm/f.rb +1 -1
- data/lib/aixm/feature/airport.rb +34 -10
- data/lib/aixm/feature/airspace.rb +3 -0
- data/lib/aixm/feature/navigational_aid/dme.rb +29 -10
- data/lib/aixm/feature/navigational_aid/marker.rb +2 -2
- data/lib/aixm/feature/navigational_aid/tacan.rb +3 -2
- data/lib/aixm/feature/navigational_aid/vor.rb +32 -13
- data/lib/aixm/feature/navigational_aid.rb +1 -1
- data/lib/aixm/feature/obstacle.rb +6 -6
- data/lib/aixm/feature/obstacle_group.rb +6 -2
- data/lib/aixm/feature/organisation.rb +1 -0
- data/lib/aixm/feature/unit.rb +2 -1
- data/lib/aixm/feature.rb +3 -0
- data/lib/aixm/memoize.rb +27 -11
- data/lib/aixm/p.rb +3 -2
- data/lib/aixm/payload_hash.rb +1 -1
- data/lib/aixm/r.rb +62 -0
- data/lib/aixm/refinements.rb +4 -4
- data/lib/aixm/version.rb +1 -1
- data/lib/aixm/w.rb +2 -1
- data/lib/aixm/xy.rb +1 -1
- data/lib/aixm/z.rb +5 -4
- data/lib/aixm.rb +10 -5
- data/schemas/ofmx/0.1/OFMX-DataTypes.xsd +6 -0
- data/schemas/ofmx/0.1/OFMX-Snapshot.xsd +5 -0
- data.tar.gz.sig +0 -0
- metadata +8 -4
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 33661b6ab9022c54a9d41dad531b0f1c53f39eaf053a6c4b8361c50543b9ae01
|
4
|
+
data.tar.gz: add22919257222a6f06dae9de21f0f71c2b941a67e6bc52dba14bde5fbae6c9a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c1fb317e1791098f127c769e5f680bbf0c30ab823c73c48f392d6ea918f1ba4c6396d4e5cb43357ef1c867bad73e475d25be95b274bad7fd9ee17ce297dbbb6f
|
7
|
+
data.tar.gz: 904a2fa5c84b80bf14a67536fa2c0f2ab26b6d34dc3dc789e272116812994f86b9c3aff92b08d1cda9b3d3495abfe990eb922f0579fd779a1602963ba28ded59
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/CHANGELOG.md
CHANGED
@@ -1,10 +1,40 @@
|
|
1
|
+
## 1.1.0
|
2
|
+
|
3
|
+
#### Breaking Changes
|
4
|
+
* `AIXM::Association:Array#duplicates` now returns an array of arrays which
|
5
|
+
group all duplicates together.
|
6
|
+
* `VOR#associate_dme` and `VOR#associate_tacan` no longer take the channel
|
7
|
+
as argument but calculate it from the (ghost) frequency of the VOR.
|
8
|
+
* Replaced `#length`/`#width` with `#dimensions` on `Runway`, `Helipad` and `FATO`
|
9
|
+
* Renamed `AIXM::D#dist` to `AIXM::D#dim`
|
10
|
+
* Renamed `TLOF#helicopter_class` to `TLOF#performance_class`
|
11
|
+
* Renamed `#geographic_orientation` and `#magnetic_orientation` to more familiar
|
12
|
+
`#geographic_bearing` and `#magnetic_bearing` on `Runway` and `FATO`
|
13
|
+
* Re-implementation of `AIXM::A` without precision
|
14
|
+
* Demoted `Address` to component
|
15
|
+
* Fixed typo in `Service` type `:vdf_direction_finding_service`
|
16
|
+
|
17
|
+
#### Additions
|
18
|
+
* Associations from `Service` to `Airport` and `Airspace`
|
19
|
+
* `AIXM::R` (rectangle)
|
20
|
+
* `Runway#marking`
|
21
|
+
* `ApproachLighting` on `Runway::Direction` and `FATO::Direction`
|
22
|
+
* `VASIS` on `Runway::Direction` and `FATO::Direction`
|
23
|
+
* `#meta` on every feature and component
|
24
|
+
* `Document#regions` which is added to the root element for OFMX
|
25
|
+
|
26
|
+
#### Changes
|
27
|
+
* Nested memoization of the same method is now allowed and won't reset the
|
28
|
+
memoization cache anymore.
|
29
|
+
* Remove unit "mhz" from `Address` of type `:radio_frequency`.
|
30
|
+
|
1
31
|
## 1.0.0
|
2
32
|
|
3
33
|
#### Breaking Changes
|
4
34
|
* Move `Ase->txtLocalType` up into `AseUid` for OFMX
|
5
35
|
|
6
36
|
#### Additions
|
7
|
-
* Add
|
37
|
+
* Add rhumb line geometry
|
8
38
|
|
9
39
|
## 0.3.11
|
10
40
|
|
@@ -19,21 +49,21 @@
|
|
19
49
|
#### Additions
|
20
50
|
* Add `f#voice?` and `AIXM.config.voice_channel_separation` to check whether a
|
21
51
|
frequency belongs to the voice communication airband and use it to validate
|
22
|
-
`
|
52
|
+
`Frequency`
|
23
53
|
|
24
54
|
## 0.3.10
|
25
55
|
|
26
56
|
#### Additions
|
27
57
|
* Proper `has_many` and `has_one` associations
|
28
|
-
* `AIXM::Association:Array#find_by|find|
|
58
|
+
* `AIXM::Association:Array#find_by|find|duplicates` on `has_many` associations
|
29
59
|
* `AIXM.config.mid` now defines whether `mid` attributes are inserted or not
|
30
60
|
provided the selected schema is OFMX
|
31
61
|
* `AIXM::Memoize` module
|
32
62
|
* `AIXM::PayloadHash` class
|
33
63
|
* `mkmid` executable to insert `mid` attributes into valid OFMX file
|
34
64
|
* `ckmid` executable to check `mid` attributes in an OFMX file
|
35
|
-
*
|
36
|
-
* `
|
65
|
+
* Geometries respond to `#point?`, `#circle?` and `#polygon?`
|
66
|
+
* `Layer#services`
|
37
67
|
|
38
68
|
#### Breaking Changes
|
39
69
|
* Require Ruby 2.7
|
@@ -63,20 +93,20 @@
|
|
63
93
|
## 0.3.7
|
64
94
|
|
65
95
|
#### Additions
|
66
|
-
* `
|
67
|
-
* `
|
96
|
+
* `Document#select_features`
|
97
|
+
* `Document#group_obstacles!`
|
68
98
|
|
69
99
|
## 0.3.6
|
70
100
|
|
71
101
|
#### Additions
|
72
|
-
* `
|
73
|
-
* `
|
102
|
+
* `FATO`
|
103
|
+
* `Helipad#helicopter_class` and `Helipad#marking`
|
74
104
|
* `AIXM::XY#seconds?` to detect possibly rounded or estimated coordinates
|
75
|
-
* `
|
105
|
+
* `Airport#operator`
|
76
106
|
* `AIXM::W` (weight)
|
77
107
|
* `AIXM::P` (pressure)
|
78
|
-
* `
|
79
|
-
* Surface details
|
108
|
+
* `Lighting` for use with runways, helipads and FATOs
|
109
|
+
* Surface details `#siwl_weight`, `#siwl_tire_pressure` and `#auw_weight`
|
80
110
|
|
81
111
|
#### Changes
|
82
112
|
* Generate `Airport#id` from region and `Airport#name`
|
@@ -242,7 +272,7 @@
|
|
242
272
|
|
243
273
|
#### Changes
|
244
274
|
* `Document#created_at` and `#effective_at` accept Time, Date, String or *nil*
|
245
|
-
* Separate `
|
275
|
+
* Separate `Document#valid?` from `#complete?`
|
246
276
|
* Write coordinates in DD if extension `:OFM` is set
|
247
277
|
* `Array#to_digest` returns Integer which fits in signed 32bit
|
248
278
|
|
data/README.md
CHANGED
@@ -47,7 +47,7 @@ gem install aixm --trust-policy MediumSecurity
|
|
47
47
|
|
48
48
|
## Usage
|
49
49
|
|
50
|
-
Here's how to build a document object, populate it with a simple feature and then render it as AIXM:
|
50
|
+
Here's how to build a document object, populate it with a simple feature and then render it as AIXM or OFMX:
|
51
51
|
|
52
52
|
```ruby
|
53
53
|
document = AIXM.document(
|
@@ -139,17 +139,16 @@ AIXM.config.ignored_errors = /invalid date/i
|
|
139
139
|
|
140
140
|
### Fundamentals
|
141
141
|
* [Document](https://www.rubydoc.info/gems/aixm/AIXM/Document.html)
|
142
|
+
* [A (angle)](https://www.rubydoc.info/gems/aixm/AIXM/A.html)
|
143
|
+
* [D (dimension, distance or length)](https://www.rubydoc.info/gems/aixm/AIXM/D.html)
|
144
|
+
* [F (frequency)](https://www.rubydoc.info/gems/aixm/AIXM/F.html)
|
145
|
+
* [P (pressure)](https://www.rubydoc.info/gems/aixm/AIXM/P.html)
|
146
|
+
* [R (rectangle)](https://www.rubydoc.info/gems/aixm/AIXM/R.html)
|
142
147
|
* [XY (longitude and latitude)](https://www.rubydoc.info/gems/aixm/AIXM/XY.html)
|
143
148
|
* [Z (height, elevation or altitude)](https://www.rubydoc.info/gems/aixm/AIXM/Z.html)
|
144
|
-
* [D (distance or length)](https://www.rubydoc.info/gems/aixm/AIXM/D.html)
|
145
|
-
* [F (frequency)](https://www.rubydoc.info/gems/aixm/AIXM/F.html)
|
146
|
-
* [A (angle)](https://www.rubydoc.info/gems/aixm/AIXM/A.html)
|
147
149
|
|
148
150
|
### Features
|
149
151
|
* [Address](https://www.rubydoc.info/gems/aixm/AIXM/Feature/Address.html)
|
150
|
-
* [Organisation](https://www.rubydoc.info/gems/aixm/AIXM/Feature/Organisation.html)
|
151
|
-
* [Unit](https://www.rubydoc.info/gems/aixm/AIXM/Feature/Unit.html)
|
152
|
-
* [Service](https://www.rubydoc.info/gems/aixm/AIXM/Component/Service.html)
|
153
152
|
* [Airport](https://www.rubydoc.info/gems/aixm/AIXM/Feature/Airport.html)
|
154
153
|
* [Airspace](https://www.rubydoc.info/gems/aixm/AIXM/Feature/Airspace.html)
|
155
154
|
* [Navigational aid](https://www.rubydoc.info/gems/aixm/AIXM/NavigationalAid.html)
|
@@ -159,22 +158,32 @@ AIXM.config.ignored_errors = /invalid date/i
|
|
159
158
|
* [NDB](https://www.rubydoc.info/gems/aixm/AIXM/Feature/NDB.html)
|
160
159
|
* [TACAN](https://www.rubydoc.info/gems/aixm/AIXM/Feature/TACAN.html)
|
161
160
|
* [VOR](https://www.rubydoc.info/gems/aixm/AIXM/Feature/VOR.html)
|
162
|
-
* [Obstacle
|
161
|
+
* [Obstacle](https://www.rubydoc.info/gems/aixm/AIXM/Feature/Obstacle.html)
|
162
|
+
* [Obstacle group](https://www.rubydoc.info/gems/aixm/AIXM/Feature/ObstacleGroup.html)
|
163
|
+
* [Organisation](https://www.rubydoc.info/gems/aixm/AIXM/Feature/Organisation.html)
|
164
|
+
* [Service](https://www.rubydoc.info/gems/aixm/AIXM/Component/Service.html)
|
165
|
+
* [Unit](https://www.rubydoc.info/gems/aixm/AIXM/Feature/Unit.html)
|
163
166
|
|
164
167
|
### Components
|
168
|
+
|
169
|
+
* [ApproachLighting](https://www.rubydoc.info/gems/aixm/AIXM/Component/ApproachLighting.html)
|
170
|
+
* [FATO](https://www.rubydoc.info/gems/aixm/AIXM/Component/FATO.html)
|
165
171
|
* [Frequency](https://www.rubydoc.info/gems/aixm/AIXM/Component/Frequency.html)
|
166
172
|
* [Geometry](https://www.rubydoc.info/gems/aixm/AIXM/Component/Geometry.html)
|
167
|
-
* [Point](https://www.rubydoc.info/gems/aixm/AIXM/Component/Point.html)
|
168
173
|
* [Arc](https://www.rubydoc.info/gems/aixm/AIXM/Component/Arc.html)
|
169
174
|
* [Border](https://www.rubydoc.info/gems/aixm/AIXM/Component/Border.html)
|
170
175
|
* [Circle](https://www.rubydoc.info/gems/aixm/AIXM/Component/Circle.html)
|
171
|
-
* [
|
176
|
+
* [Point](https://www.rubydoc.info/gems/aixm/AIXM/Component/Point.html)
|
177
|
+
* [RhumbLine](https://www.rubydoc.info/gems/aixm/AIXM/Component/RhumbLine.html)
|
172
178
|
* [Helipad](https://www.rubydoc.info/gems/aixm/AIXM/Component/Helipad.html)
|
173
|
-
* [FATO](https://www.rubydoc.info/gems/aixm/AIXM/Component/FATO.html)
|
174
|
-
* [Surface](https://www.rubydoc.info/gems/aixm/AIXM/Component/Surface.html)
|
175
179
|
* [Layer](https://www.rubydoc.info/gems/aixm/AIXM/Component/Layer.html)
|
176
|
-
* [
|
180
|
+
* [Lighting](https://www.rubydoc.info/gems/aixm/AIXM/Component/Lighting.html)
|
181
|
+
* [Runway](https://www.rubydoc.info/gems/aixm/AIXM/Component/Runway.html)
|
182
|
+
* [Service](https://www.rubydoc.info/gems/aixm/AIXM/Component/Service.html)
|
183
|
+
* [Surface](https://www.rubydoc.info/gems/aixm/AIXM/Component/Surface.html)
|
177
184
|
* [Timetable](https://www.rubydoc.info/gems/aixm/AIXM/Component/Timetable.html)
|
185
|
+
* [VASIS](https://www.rubydoc.info/gems/aixm/AIXM/Component/VASIS.html)
|
186
|
+
* [Vertical limit](https://www.rubydoc.info/gems/aixm/AIXM/Component/VerticalLimit.html)
|
178
187
|
|
179
188
|
## Associations
|
180
189
|
|
@@ -204,6 +213,14 @@ document.features.find(airport) # => [#<AIXM::Feature::Airport>]
|
|
204
213
|
|
205
214
|
This may seem redundant at first, but keep in mind that two instances of +AIXM::CLASSES+ which implement `#to_uid` are considered equal if they are instances of the same class and both their UIDs as calculated by `#to_uid` are equal. Attributes which are not part of the `#to_uid` calculation are irrelevant!
|
206
215
|
|
216
|
+
### meta
|
217
|
+
|
218
|
+
You can write arbitrary meta information to any feature or component. It won't be used when building the AIXM or OFMX document, in fact, it is not used by this gem at all. But you can store e.g. foreign keys and then later use them to find a feature or component like so:
|
219
|
+
|
220
|
+
```ruby
|
221
|
+
document.features.find_by(:airport, meta: 1234) # 1234 is the foreign key
|
222
|
+
```
|
223
|
+
|
207
224
|
### duplicates
|
208
225
|
|
209
226
|
Equally on `has_many` associations, use `duplicates` to find identical or equal associations:
|
@@ -282,13 +299,7 @@ bundle exec rake # run tests once
|
|
282
299
|
bundle exec guard # run tests whenever files are modified
|
283
300
|
```
|
284
301
|
|
285
|
-
|
286
|
-
|
287
|
-
https://github.com/svoop/aixm/issues
|
288
|
-
|
289
|
-
To contribute code, fork the project on Github, add your code and submit a pull request:
|
290
|
-
|
291
|
-
https://help.github.com/articles/fork-a-repo
|
302
|
+
You're welcome to [submit issues](https://github.com/svoop/aixm/issues) and contribute code by [forking the project and submitting pull requests](https://docs.github.com/en/get-started/quickstart/fork-a-repo).
|
292
303
|
|
293
304
|
## License
|
294
305
|
|
data/lib/aixm/a.rb
CHANGED
@@ -2,53 +2,48 @@ using AIXM::Refinements
|
|
2
2
|
|
3
3
|
module AIXM
|
4
4
|
|
5
|
-
# Angle
|
6
|
-
#
|
5
|
+
# Angle in the range of -360 < angle < 360 degrees (used for azimuths or
|
6
|
+
# courses) and with an optional one-letter suffix (used for runways).
|
7
7
|
#
|
8
|
-
# @example
|
9
|
-
#
|
10
|
-
# a
|
11
|
-
# a
|
12
|
-
# a
|
13
|
-
# a
|
14
|
-
# a.deg += 7 # => 19
|
15
|
-
# a.deg += 341 # => 0 - deg is always within (0..359)
|
16
|
-
# a.to_s # => "000" - to_s is always within ("000".."359")
|
8
|
+
# @example Initialization
|
9
|
+
# AIXM.a(-36.9) # => #<AIXM::A -36.9° "32">
|
10
|
+
# AIXM.a(12) # => #<AIXM::A 12° "01">
|
11
|
+
# AIXM.a("12L") # => #<AIXM::A 120° "12L">
|
12
|
+
# AIXM.a(360) # => #<AIXM::A 0° "36">
|
13
|
+
# AIXM.a(-400) # => #<AIXM::A -40° "32">
|
17
14
|
#
|
18
|
-
# @example
|
19
|
-
# a = AIXM.a(
|
20
|
-
# a
|
21
|
-
# a.
|
22
|
-
# a.
|
23
|
-
# a.
|
24
|
-
# a.
|
25
|
-
# a.
|
26
|
-
# a.
|
15
|
+
# @example Calculations
|
16
|
+
# a = AIXM.a("02L")
|
17
|
+
# a += 5 # => #<AIXM::A 25° "03L">
|
18
|
+
# a -= AIXM.a(342.8) # => #<AIXM::A -317.8° "04L">
|
19
|
+
# a.to_s # => "-317.8°"
|
20
|
+
# a.to_s(:runway) # => "04L"
|
21
|
+
# a.to_s(:bearing) # => "042.2000"
|
22
|
+
# a.to_f # => 42.2
|
23
|
+
# a.to_i # => 42
|
24
|
+
# a.invert # => #<AIXM::A -137.8° "22R">
|
25
|
+
# a.to_s(:runway) # => "22R"
|
27
26
|
class A
|
28
27
|
SUFFIX_INVERSIONS = {
|
29
28
|
R: :L,
|
30
29
|
L: :R
|
31
30
|
}.freeze
|
32
31
|
|
33
|
-
|
34
|
-
attr_reader :deg
|
32
|
+
RUNWAY_RE = /\A(0[1-9]|[12]\d|3[0-6])([A-Z])?\z/
|
35
33
|
|
36
|
-
# @return [Integer]
|
37
|
-
attr_reader :
|
34
|
+
# @return [Integer] angle in the range of -360 < angle < 360
|
35
|
+
attr_reader :deg
|
38
36
|
|
39
|
-
# @return [Symbol, nil] suffix
|
37
|
+
# @return [Symbol, nil] one-letter suffix
|
40
38
|
attr_reader :suffix
|
41
39
|
|
42
|
-
def initialize(
|
43
|
-
case
|
44
|
-
when Numeric
|
45
|
-
self.deg, @precision = deg_and_suffix, 3
|
40
|
+
def initialize(value)
|
41
|
+
case value
|
46
42
|
when String
|
47
|
-
fail(ArgumentError, "invalid angle") unless
|
48
|
-
self.deg,
|
49
|
-
when
|
50
|
-
|
51
|
-
@deg, @precision = 0, deg_and_suffix.to_s.to_i
|
43
|
+
fail(ArgumentError, "invalid angle") unless value =~ RUNWAY_RE
|
44
|
+
self.deg, self.suffix = $1.to_i * 10, $2
|
45
|
+
when Numeric
|
46
|
+
self.deg = value
|
52
47
|
else
|
53
48
|
fail(ArgumentError, "invalid angle")
|
54
49
|
end
|
@@ -56,39 +51,62 @@ module AIXM
|
|
56
51
|
|
57
52
|
# @return [String]
|
58
53
|
def inspect
|
59
|
-
%Q(#<#{self.class}
|
54
|
+
%Q(#<#{self.class} #{to_s} #{to_s(:runway).inspect}>)
|
60
55
|
end
|
61
56
|
|
62
|
-
# @return [
|
63
|
-
def
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
57
|
+
# @return [Integer] within 0..359
|
58
|
+
def to_i
|
59
|
+
(deg.round + 360) % 360
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [Float] within 0.0..359.9~
|
63
|
+
def to_f
|
64
|
+
((deg + 360) % 360).to_f
|
65
|
+
end
|
66
|
+
|
67
|
+
# Degrees as formatted string
|
68
|
+
#
|
69
|
+
# Types are:
|
70
|
+
# * :human - degrees within -359.9~..359.9~ as D.D° (default)
|
71
|
+
# * :bearing - degrees within 0.0..359.9~ as DDD.DDDD
|
72
|
+
# * :runway - degrees within "01".."36" plus optional suffix
|
73
|
+
#
|
74
|
+
# @param type [Symbol, nil] either :runway, :bearing or nil
|
75
|
+
# @param unit [String] unit to postfix
|
76
|
+
# @return [String]
|
77
|
+
def to_s(type=:human)
|
78
|
+
return '' unless deg
|
79
|
+
case type
|
80
|
+
when :runway then [('%02d' % (((deg / 10).round + 35) % 36 + 1)), suffix].join
|
81
|
+
when :bearing then '%08.4f' % to_f.round(4)
|
82
|
+
when :human then [deg.to_s('F').sub(/\.0$/, ''), '°'].join
|
83
|
+
else fail ArgumentError
|
68
84
|
end
|
69
85
|
end
|
70
86
|
|
71
87
|
def deg=(value)
|
72
|
-
fail(ArgumentError, "invalid deg `#{value}'") unless value.is_a?
|
73
|
-
|
88
|
+
fail(ArgumentError, "invalid deg `#{value}'") unless value.is_a? Numeric
|
89
|
+
normalized_value = value.abs % 360
|
90
|
+
sign = '-' if value.negative? && normalized_value.nonzero?
|
91
|
+
@deg = BigDecimal("#{sign}#{normalized_value}")
|
74
92
|
end
|
75
93
|
|
76
94
|
def suffix=(value)
|
77
|
-
fail(
|
78
|
-
fail(ArgumentError, "invalid suffix") unless value.nil? || value.to_s =~ /\A[A-Z]+\z/
|
95
|
+
fail(ArgumentError, "invalid suffix") unless value.nil? || value.to_s =~ /\A[A-Z]\z/
|
79
96
|
@suffix = value&.to_s&.to_sym
|
80
97
|
end
|
81
98
|
|
82
99
|
# Invert an angle by 180 degrees
|
83
100
|
#
|
84
101
|
# @example
|
85
|
-
# AIXM.a(120).invert #
|
86
|
-
# AIXM.a("34L").invert #
|
87
|
-
# AIXM.a("33X").invert # => AIXM.a("33X")
|
102
|
+
# AIXM.a(120).invert # (300°)
|
103
|
+
# AIXM.a("34L").invert # (160° suffix "R")
|
88
104
|
#
|
89
105
|
# @return [AIXM::A] inverted angle
|
90
106
|
def invert
|
91
|
-
|
107
|
+
self.class.new(deg.negative? ? deg - 180 : deg + 180).tap do |angle|
|
108
|
+
angle.suffix = SUFFIX_INVERSIONS.fetch(suffix, suffix)
|
109
|
+
end
|
92
110
|
end
|
93
111
|
|
94
112
|
# Check whether +other+ angle is the inverse
|
@@ -104,47 +122,47 @@ module AIXM
|
|
104
122
|
invert == other
|
105
123
|
end
|
106
124
|
|
107
|
-
#
|
125
|
+
# Negate degrees
|
108
126
|
#
|
109
127
|
# @return [AIXM::A]
|
110
|
-
def
|
111
|
-
|
112
|
-
build(precision: precision, deg: (deg + numeric_or_angle.round) % 360, suffix: suffix)
|
128
|
+
def -@
|
129
|
+
deg.zero? ? self : self.class.new(-deg).tap { _1.suffix = suffix }
|
113
130
|
end
|
114
131
|
|
115
|
-
#
|
132
|
+
# Add degrees
|
116
133
|
#
|
134
|
+
# @param value [Numeric, AIXM::A]
|
117
135
|
# @return [AIXM::A]
|
118
|
-
def
|
119
|
-
|
120
|
-
|
136
|
+
def +(value)
|
137
|
+
case value
|
138
|
+
when Numeric
|
139
|
+
value.zero? ? self : self.class.new(deg + value).tap { _1.suffix = suffix }
|
140
|
+
when AIXM::A
|
141
|
+
value.deg.zero? ? self : self.class.new(deg + value.deg).tap { _1.suffix = suffix }
|
142
|
+
else
|
143
|
+
fail ArgumentError
|
144
|
+
end
|
121
145
|
end
|
122
146
|
|
123
|
-
#
|
124
|
-
|
125
|
-
|
147
|
+
# Subtract degrees
|
148
|
+
#
|
149
|
+
# @param value [Numeric, AIXM::A]
|
150
|
+
# @return [AIXM::A]
|
151
|
+
def -(value)
|
152
|
+
self + -value
|
126
153
|
end
|
127
154
|
|
128
155
|
# @see Object#==
|
129
156
|
# @return [Boolean]
|
130
157
|
def ==(other)
|
131
|
-
self.class === other && deg == other.deg &&
|
158
|
+
self.class === other && deg == other.deg && suffix == other.suffix
|
132
159
|
end
|
133
160
|
alias_method :eql?, :==
|
134
161
|
|
135
162
|
# @see Object#hash
|
136
163
|
# @return [Integer]
|
137
164
|
def hash
|
138
|
-
|
139
|
-
end
|
140
|
-
|
141
|
-
private
|
142
|
-
|
143
|
-
def build(precision:, deg:, suffix: nil)
|
144
|
-
self.class.new(precision.to_s.to_sym).tap do |a|
|
145
|
-
a.deg = deg
|
146
|
-
a.suffix = suffix
|
147
|
-
end
|
165
|
+
[deg, suffix].join.hash
|
148
166
|
end
|
149
167
|
end
|
150
168
|
|
data/lib/aixm/association.rb
CHANGED
@@ -23,18 +23,18 @@ module AIXM
|
|
23
23
|
# end
|
24
24
|
# blog, post = Blog.new, Post.new
|
25
25
|
# # --either--
|
26
|
-
# blog.add_post(post)
|
26
|
+
# blog.add_post(post) # => Blog
|
27
27
|
# blog.posts.count # => 1
|
28
28
|
# blog.posts.first == post # => true
|
29
29
|
# post.blog == blog # => true
|
30
|
-
# blog.remove_post(post)
|
30
|
+
# blog.remove_post(post) # => Blog
|
31
31
|
# blog.posts.count # => 0
|
32
32
|
# # --or--
|
33
|
-
# post.blog = blog
|
33
|
+
# post.blog = blog # => Blog
|
34
34
|
# blog.posts.count # => 1
|
35
35
|
# blog.posts.first == post # => true
|
36
36
|
# post.blog == blog # => true
|
37
|
-
# post.blog = nil
|
37
|
+
# post.blog = nil # => nil
|
38
38
|
# blog.posts.count # => 0
|
39
39
|
# # --or--
|
40
40
|
# post_2 = Post.new
|
@@ -53,19 +53,21 @@ module AIXM
|
|
53
53
|
# end
|
54
54
|
# blog, post = Blog.new, Post.new
|
55
55
|
# # --either--
|
56
|
-
# blog.post = post
|
57
|
-
# blog.post
|
58
|
-
# post
|
59
|
-
# blog
|
60
|
-
# blog.post
|
61
|
-
# post
|
56
|
+
# blog.post = post # => Post (standard assignment)
|
57
|
+
# blog.add_post(post) # => Blog (alternative for chaining)
|
58
|
+
# blog.post == post # => true
|
59
|
+
# post.blog == blog # => true
|
60
|
+
# blog.post = nil # => nil
|
61
|
+
# blog.post # => nil
|
62
|
+
# post.blog # => nil
|
62
63
|
# # --or--
|
63
|
-
# post.blog = blog
|
64
|
-
# post.blog
|
65
|
-
# blog
|
66
|
-
# post
|
67
|
-
# post.blog
|
68
|
-
# blog
|
64
|
+
# post.blog = blog # => Blog (standard assignment)
|
65
|
+
# post.add_blog(blog) # => Post (alternative for chaining)
|
66
|
+
# post.blog == blog # => true
|
67
|
+
# blog.post == post # => true
|
68
|
+
# post.blog = nil # => nil
|
69
|
+
# post.blog # => nil
|
70
|
+
# blog.post # => nil
|
69
71
|
#
|
70
72
|
# @example Association with readonly +belongs_to+ (idem for +has_one+)
|
71
73
|
# class Blog
|
@@ -218,14 +220,19 @@ module AIXM
|
|
218
220
|
(@has_one_attributes ||= []) << attribute
|
219
221
|
# feature
|
220
222
|
attr_reader attribute
|
221
|
-
# feature=
|
223
|
+
# feature=
|
222
224
|
define_method(:"#{association}=") do |object|
|
223
225
|
fail(ArgumentError, "#{object.__class__} not allowed") unless class_names.any? { |c| object.is_a?(c.to_class) }
|
224
226
|
instance_variable_get(:"@#{attribute}")&.instance_variable_set(:"@#{inversion}", nil)
|
225
227
|
instance_variable_set(:"@#{attribute}", object)
|
226
228
|
object&.instance_variable_set(:"@#{inversion}", self)
|
229
|
+
object
|
230
|
+
end
|
231
|
+
# add_feature
|
232
|
+
define_method(:"add_#{association}") do |object|
|
233
|
+
send("#{association}=", object)
|
234
|
+
self
|
227
235
|
end
|
228
|
-
alias_method(:"add_#{association}", :"#{association}=")
|
229
236
|
# remove_feature
|
230
237
|
define_method(:"remove_#{association}") do |_|
|
231
238
|
send(:"#{association}=", nil)
|
@@ -239,11 +246,17 @@ module AIXM
|
|
239
246
|
(@belongs_to_attributes ||= []) << attribute
|
240
247
|
# feature
|
241
248
|
attr_reader attribute
|
242
|
-
# feature=
|
243
249
|
unless readonly
|
250
|
+
# feature=
|
244
251
|
define_method(:"#{attribute}=") do |object|
|
245
252
|
instance_variable_get(:"@#{attribute}")&.send(:"remove_#{inversion}", self)
|
246
253
|
object&.send(:"add_#{inversion}", self)
|
254
|
+
object
|
255
|
+
end
|
256
|
+
# add_feature
|
257
|
+
define_method(:"add_#{attribute}") do |object|
|
258
|
+
send("#{attribute}=", object)
|
259
|
+
self
|
247
260
|
end
|
248
261
|
end
|
249
262
|
end
|
@@ -349,17 +362,14 @@ module AIXM
|
|
349
362
|
# belongs_to :blog
|
350
363
|
# end
|
351
364
|
# blog, post = Blog.new, Post.new
|
352
|
-
#
|
353
|
-
# blog.
|
365
|
+
# duplicate_post = post.dup
|
366
|
+
# blog.add_posts([post, duplicate_post])
|
367
|
+
# blog.posts.duplicates # => [[post, duplicate_post]]
|
354
368
|
#
|
355
|
-
# @return [AIXM::
|
369
|
+
# @return [Array<Array<AIXM::Feature>>]
|
356
370
|
def duplicates
|
357
371
|
AIXM::Memoize.method :to_uid do
|
358
|
-
|
359
|
-
select.with_index do |element, index|
|
360
|
-
index != self.index(element)
|
361
|
-
end
|
362
|
-
)
|
372
|
+
group_by(&:to_uid).select { |_, a| a.count > 1 }.map(&:last)
|
363
373
|
end
|
364
374
|
end
|
365
375
|
end
|
data/lib/aixm/classes.rb
CHANGED
@@ -6,11 +6,13 @@ module AIXM
|
|
6
6
|
xy: 'AIXM::XY',
|
7
7
|
z: 'AIXM::Z',
|
8
8
|
d: 'AIXM::D',
|
9
|
+
r: 'AIXM::R',
|
9
10
|
f: 'AIXM::F',
|
10
11
|
a: 'AIXM::A',
|
11
12
|
w: 'AIXM::W',
|
12
13
|
p: 'AIXM::P',
|
13
|
-
address: 'AIXM::
|
14
|
+
address: 'AIXM::Component::Address',
|
15
|
+
approach_lighting: 'AIXM::Component::ApproachLighting',
|
14
16
|
organisation: 'AIXM::Feature::Organisation',
|
15
17
|
unit: 'AIXM::Feature::Unit',
|
16
18
|
service: 'AIXM::Component::Service',
|
@@ -38,7 +40,8 @@ module AIXM
|
|
38
40
|
vor: 'AIXM::Feature::NavigationalAid::VOR',
|
39
41
|
obstacle: 'AIXM::Feature::Obstacle',
|
40
42
|
obstacle_group: 'AIXM::Feature::ObstacleGroup',
|
41
|
-
timetable: 'AIXM::Component::Timetable'
|
43
|
+
timetable: 'AIXM::Component::Timetable',
|
44
|
+
vasis: 'AIXM::Component::VASIS'
|
42
45
|
}.freeze
|
43
46
|
|
44
47
|
end
|
@@ -1,20 +1,19 @@
|
|
1
1
|
using AIXM::Refinements
|
2
2
|
|
3
3
|
module AIXM
|
4
|
-
class
|
4
|
+
class Component
|
5
5
|
|
6
6
|
# Address or similar means to contact an entity.
|
7
7
|
#
|
8
8
|
# ===Cheat Sheet in Pseudo Code:
|
9
9
|
# address = AIXM.address(
|
10
|
-
# source: String or nil
|
11
10
|
# type: TYPES
|
12
11
|
# address: AIXM.f (type :radio_frequency) or String (other types)
|
13
12
|
# )
|
14
|
-
#
|
13
|
+
# address.remarks = String or nil
|
15
14
|
#
|
16
15
|
# @see https://gitlab.com/openflightmaps/ofmx/wikis/Airport#aha-airport-address
|
17
|
-
class Address <
|
16
|
+
class Address < Component
|
18
17
|
include AIXM::Association
|
19
18
|
include AIXM::Memoize
|
20
19
|
|
@@ -34,7 +33,7 @@ module AIXM
|
|
34
33
|
'URL-MET': :weather_url,
|
35
34
|
RADIO: :radio_frequency,
|
36
35
|
OTHER: :other # specify in remarks
|
37
|
-
}
|
36
|
+
}.freeze
|
38
37
|
|
39
38
|
# @!method addressable
|
40
39
|
# @return [AIXM::Feature] addressable feature
|
@@ -49,8 +48,7 @@ module AIXM
|
|
49
48
|
# @return [String, nil] free text remarks
|
50
49
|
attr_reader :remarks
|
51
50
|
|
52
|
-
def initialize(
|
53
|
-
super(source: source, region: region)
|
51
|
+
def initialize(type:, address:)
|
54
52
|
self.type, self.address = type, address
|
55
53
|
end
|
56
54
|
|
@@ -93,9 +91,14 @@ module AIXM
|
|
93
91
|
def to_xml(as:, sequence:)
|
94
92
|
builder = Builder::XmlMarkup.new(indent: 2)
|
95
93
|
builder.comment! ["Address: #{TYPES.key(type)}", addressable&.id].compact.join(' for ')
|
96
|
-
builder.tag!(as
|
94
|
+
builder.tag!(as) do |tag|
|
97
95
|
tag << to_uid(as: :"#{as}Uid", sequence: sequence).indent(2)
|
98
|
-
|
96
|
+
case type
|
97
|
+
when :radio_frequency
|
98
|
+
tag.txtAddress(address.freq.to_s)
|
99
|
+
else
|
100
|
+
tag.txtAddress(address)
|
101
|
+
end
|
99
102
|
tag.txtRmk(remarks) if remarks
|
100
103
|
end
|
101
104
|
end
|