aixm 0.1.0 → 0.1.3
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 +29 -1
- data/Guardfile +1 -1
- data/README.md +146 -17
- data/aixm.gemspec +3 -1
- data/lib/aixm.rb +12 -10
- data/lib/aixm/component/base.rb +6 -0
- data/lib/aixm/component/class_layer.rb +49 -0
- data/lib/aixm/component/geometry.rb +73 -0
- data/lib/aixm/component/geometry/arc.rb +53 -0
- data/lib/aixm/component/geometry/border.rb +49 -0
- data/lib/aixm/component/geometry/circle.rb +56 -0
- data/lib/aixm/component/geometry/point.rb +42 -0
- data/lib/aixm/component/schedule.rb +45 -0
- data/lib/aixm/{vertical/limits.rb → component/vertical_limits.rb} +9 -14
- data/lib/aixm/document.rb +30 -19
- data/lib/aixm/feature/airspace.rb +60 -29
- data/lib/aixm/refinements.rb +49 -2
- data/lib/aixm/shortcuts.rb +30 -0
- data/lib/aixm/version.rb +1 -1
- data/spec/factory.rb +42 -25
- data/spec/lib/aixm/component/class_layer_spec.rb +74 -0
- data/spec/lib/aixm/{horizontal → component/geometry}/arc_spec.rb +11 -11
- data/spec/lib/aixm/component/geometry/border_spec.rb +30 -0
- data/spec/lib/aixm/{horizontal → component/geometry}/circle_spec.rb +8 -8
- data/spec/lib/aixm/{horizontal → component/geometry}/point_spec.rb +7 -7
- data/spec/lib/aixm/{geometry_spec.rb → component/geometry_spec.rb} +39 -40
- data/spec/lib/aixm/component/schedule_spec.rb +33 -0
- data/spec/lib/aixm/{vertical/limits_spec.rb → component/vertical_limits_spec.rb} +10 -10
- data/spec/lib/aixm/document_spec.rb +97 -36
- data/spec/lib/aixm/feature/airspace_spec.rb +230 -71
- data/spec/lib/aixm/refinements_spec.rb +52 -12
- metadata +30 -23
- data/lib/aixm/constants.rb +0 -6
- data/lib/aixm/geometry.rb +0 -71
- data/lib/aixm/horizontal/arc.rb +0 -50
- data/lib/aixm/horizontal/border.rb +0 -45
- data/lib/aixm/horizontal/circle.rb +0 -53
- data/lib/aixm/horizontal/point.rb +0 -39
- data/spec/lib/aixm/horizontal/border_spec.rb +0 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c00283d4f8eeb7bc39a916e5d71778bcb9398ccd27d8bd0dd118b452f4d897b6
|
4
|
+
data.tar.gz: 3d8c7cdf302994e590add9864ac684e98147fdc546e5ca3983bd5f68d498e3ea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0adb07ef827f44488bb89739155ee4c038a300f18590ba652d1a06771fefb4b8b72d50a203c4790d3d8a551f4c5992fcca8d73de68c50cd6c1d4732505ffeb1f
|
7
|
+
data.tar.gz: a3f7cc1facbbae82eddf970e0eb240753c46f0cc4194c477ff44a0537ff5724764179a09ab9366cdf37665b5df7e2dfb2dae9431f4c8d0500aa1144a4a4b6437
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,33 @@
|
|
1
|
+
## 0.1.3
|
2
|
+
|
3
|
+
* Breaking major changes:
|
4
|
+
* Re-organization of classes in features and components
|
5
|
+
* Additions:
|
6
|
+
* Shortcut initializers e.g. `AIXM.airspace(...)`
|
7
|
+
|
8
|
+
## 0.1.2
|
9
|
+
|
10
|
+
* Breaking additions:
|
11
|
+
* Class layers
|
12
|
+
* Breaking minor changes:
|
13
|
+
* Use `document.features << (feature)` instead of `document << (feature)`
|
14
|
+
|
15
|
+
## 0.1.1
|
16
|
+
|
17
|
+
* Additions:
|
18
|
+
* Schedule (all but `TIMSH`)
|
19
|
+
* Refinement `Float#to_km` and `String#uptrans`
|
20
|
+
* Shortcut constants `AIXM::UNLIMITED` and `AIXM::H24`
|
21
|
+
* `Airspace#short_name`
|
22
|
+
* Minor changes:
|
23
|
+
* `Document#created_at` and `#effective_at` accept Time, Date, String or *nil*
|
24
|
+
* Separate `AIXM::Document#valid?` from `#complete?`
|
25
|
+
* Write coordinates in DD if extension `:OFM` is set
|
26
|
+
* `Array#to_digest` returns Integer which fits in signed 32bit
|
27
|
+
|
1
28
|
## 0.1.0
|
2
29
|
|
3
|
-
* Initial implementation to import D/R/P zones to OFM
|
30
|
+
* Initial implementation to import D/R/P zones to OFM:
|
4
31
|
* XY Coordinate
|
5
32
|
* Z Altitude
|
6
33
|
* AIXM-Snapshot 4.5 Document
|
@@ -11,4 +38,5 @@
|
|
11
38
|
* Arc
|
12
39
|
* Border
|
13
40
|
* Circle
|
41
|
+
* Shortcut constant `AIXM::GROUND`
|
14
42
|
* Refinements
|
data/Guardfile
CHANGED
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
[](https://travis-ci.org/svoop/aixm)
|
3
3
|
[](https://codeclimate.com/github/svoop/aixm)
|
4
4
|
[](https://gitter.im/svoop/aixm)
|
5
|
-
[](https://donorbox.org/bitcetera
|
5
|
+
[](https://donorbox.org/bitcetera)
|
6
6
|
|
7
7
|
# AIXM
|
8
8
|
|
@@ -14,11 +14,12 @@ are part of this gem. Most notably, the gem is only a builder of AIXM 4.5
|
|
14
14
|
snapshot files and does not parse them.
|
15
15
|
|
16
16
|
* [Homepage](https://github.com/svoop/aixm)
|
17
|
+
* [API](http://www.rubydoc.info/gems/aixm)
|
17
18
|
* Author: [Sven Schwyn - Bitcetera](http://www.bitcetera.com)
|
18
19
|
|
19
20
|
## Install
|
20
21
|
|
21
|
-
Add this to your
|
22
|
+
Add this to your `Gemfile`:
|
22
23
|
|
23
24
|
```ruby
|
24
25
|
gem aixm
|
@@ -26,29 +27,131 @@ gem aixm
|
|
26
27
|
|
27
28
|
## Usage
|
28
29
|
|
29
|
-
|
30
|
+
You can initialize all elements either traditionally or by use of shorter
|
31
|
+
AIXM class methods:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
AIXM::Feature::Airspace.new(...)
|
35
|
+
AIXM.airspace(...)
|
36
|
+
```
|
37
|
+
|
38
|
+
### Fundamentals
|
39
|
+
|
40
|
+
All fundamentals are bundled at the root of the module `AIXM`.
|
41
|
+
|
42
|
+
### Document
|
43
|
+
|
44
|
+
The document is the root container of the AIXM snapshot file to be generated.
|
45
|
+
It's essentially a collection of features:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
document = AIXM.document(created_at: Time.now, effective_at: Time.now)
|
49
|
+
document.features << AIXM.airspace(...)
|
50
|
+
```
|
51
|
+
|
52
|
+
To give an overview of the AIXM building blocks, the remainder of this guide
|
53
|
+
will list initializer arguments with colons (`name: class`) and attribute
|
54
|
+
writers with equal or push signs (`name = class` or `name << class`):
|
55
|
+
|
56
|
+
* AIXM.document
|
57
|
+
* created_at: Time, Date or String
|
58
|
+
* effective_at: Time, Date or String
|
59
|
+
* features << AIXM::Feature
|
60
|
+
|
61
|
+
See [the API documentation](http://www.rubydoc.info/gems/aixm) for details and
|
62
|
+
[spec/factory.rb](https://github.com/svoop/aixm/blob/master/spec/factory.rb) for
|
63
|
+
examples.
|
30
64
|
|
31
65
|
#### Coordinate
|
32
66
|
|
33
67
|
All of the below are equivalent:
|
34
68
|
|
35
69
|
```ruby
|
36
|
-
AIXM
|
37
|
-
AIXM
|
38
|
-
AIXM
|
70
|
+
AIXM.xy(lat: %q(11°22'33.44"), long: %q(-111°22'33.44"))
|
71
|
+
AIXM.xy(lat: '112233.44N', long: '1112233.44W')
|
72
|
+
AIXM.xy(lat: 11.375955555555556, long: -111.37595555555555)
|
39
73
|
```
|
40
74
|
|
41
|
-
#### Altitude
|
75
|
+
#### Altitude and Heights
|
76
|
+
|
77
|
+
Altitudes and heights exist in three different forms:
|
42
78
|
|
43
79
|
```ruby
|
44
|
-
AIXM
|
45
|
-
AIXM
|
46
|
-
AIXM
|
80
|
+
AIXM.z(alt: 1000, code: :QFE) # height: 1000ft above ground
|
81
|
+
AIXM.z(alt: 2000, code: :QNH) # altitude: of 2000ft above mean sea level
|
82
|
+
AIXM.z(alt: 45, code: :QNE) # altitude: flight level 45
|
47
83
|
```
|
48
84
|
|
49
|
-
###
|
85
|
+
### Features
|
86
|
+
|
87
|
+
All features are subclasses of `AIXM::Feature`.
|
88
|
+
|
89
|
+
#### Airspace
|
90
|
+
|
91
|
+
* AIXM.airspace
|
92
|
+
* name: String
|
93
|
+
* short_name: String or *nil*
|
94
|
+
* type: String or Symbol
|
95
|
+
* schedule = AIXM.schedule
|
96
|
+
* geometry << AIXM.point, AIXM.arc, AIXM.border or AIXM.circle
|
97
|
+
* class_layers << AIXM.class_layer
|
98
|
+
* remarks = String
|
99
|
+
|
100
|
+
### Components
|
101
|
+
|
102
|
+
All components are subclasses of `AIXM::Component`.
|
103
|
+
|
104
|
+
#### Schedule
|
50
105
|
|
51
|
-
|
106
|
+
* AIXM.schedule
|
107
|
+
* code: String or Symbol
|
108
|
+
|
109
|
+
#### Class Layer
|
110
|
+
|
111
|
+
* AIXM.class_layer
|
112
|
+
* class: String or *nil*
|
113
|
+
* vertical_limits: AIXM.vertical_limits
|
114
|
+
|
115
|
+
#### Vertical Limits
|
116
|
+
|
117
|
+
* AIXM.vertical_limits
|
118
|
+
* max_z: AIXM.z or *nil*
|
119
|
+
* upper_z: AIXM.z
|
120
|
+
* lower_z: AIXM.z
|
121
|
+
* min_z: AIXM.z or *nil*
|
122
|
+
|
123
|
+
#### Point, Arc, Border and Circle
|
124
|
+
|
125
|
+
* AIXM.point
|
126
|
+
* xy: AIXM.xy
|
127
|
+
* AIXM.arc
|
128
|
+
* xy: AIXM.xy
|
129
|
+
* center_xy: AIXM.xy
|
130
|
+
* cloclwise: *true* or *false*
|
131
|
+
* AIXM.border
|
132
|
+
* xy: AIXM.xy
|
133
|
+
* name: String
|
134
|
+
* AIXM.circle
|
135
|
+
* center_xy: AIXM.xy
|
136
|
+
* radius: Numeric
|
137
|
+
|
138
|
+
#### Geometry
|
139
|
+
|
140
|
+
* AIXM.geometry
|
141
|
+
* << AIXM.point, AIXM.arc, AIXM.border or AIXM.circle
|
142
|
+
|
143
|
+
For a geometry to be complete, it must be comprised of either:
|
144
|
+
|
145
|
+
* exactly one circle
|
146
|
+
* at least three points, arcs or borders (the last of which a point with
|
147
|
+
identical coordinates as the first)
|
148
|
+
|
149
|
+
## Validation
|
150
|
+
|
151
|
+
* Use `AIXM::Document#complete?` to check whether all mandatory information is
|
152
|
+
present. Airspaces, geometries etc have `complete?` methods as well.
|
153
|
+
* Use `AIXM::Document#valid?` to validate the resulting AIXM against the XSD
|
154
|
+
schema. If any, you find the errors in `AIXM::Document#errors`.
|
52
155
|
|
53
156
|
## Rendering
|
54
157
|
|
@@ -59,16 +162,33 @@ document.to_xml(:OFM) # render AIXM 4.5 + OFM extensions XML
|
|
59
162
|
|
60
163
|
## Constants
|
61
164
|
|
62
|
-
*
|
165
|
+
* `AIXM::GROUND` - height: 0ft above ground
|
166
|
+
* `AIXM::UNLIMITED` - altitude: FL 999
|
167
|
+
* `AIXM::H24` - continuous schedule
|
63
168
|
|
64
169
|
## Refinements
|
65
170
|
|
66
171
|
By `using AIXM::Refinements` you get the following general purpose methods:
|
67
172
|
|
68
|
-
*
|
69
|
-
*
|
70
|
-
*
|
71
|
-
*
|
173
|
+
* `String#indent(number)`<br>Indent every line of a string with *number* spaces
|
174
|
+
* `String#uptrans`<br>upcase and transliterate to match the reduced character set for names
|
175
|
+
* `String#to_dd`<br>Convert DMS angle to DD or `nil` if the format is not recognized
|
176
|
+
* `Float#to_dms(padding)`<br>Convert DD angle to DMS with the degrees zero padded to *padding* length
|
177
|
+
* `Float#trim`<br>Convert whole numbers to Integer and leave all other untouched
|
178
|
+
* `Float#to_km(from: unit)`<br>Convert a distance from *unit* (:km, :m, :nm or :ft) to km
|
179
|
+
|
180
|
+
## Extensions
|
181
|
+
|
182
|
+
### OFM
|
183
|
+
|
184
|
+
This extension adds proprietary tags and attributes (most of which are prefixed
|
185
|
+
with `xt_`) aiming to improve importing the resulting AIXM into the OFM
|
186
|
+
originative suite:
|
187
|
+
|
188
|
+
* `<AIXM-Snapshot version="4.5 + OFM extensions of version 0.1" (...) />`<br>root node with extended version string
|
189
|
+
* `<Ase xt_classLayersAvail="(true|false)">`<br>true when multiple class layers and therefore an Adg-node is present
|
190
|
+
* `<xt_selAvail>(true|false)</xt_selAvail>`<br>enables conditional airspaces feature
|
191
|
+
* `<AseUid newEntity="(true|false)">`<br>tell the importer whether adding a new or updating an existing entity
|
72
192
|
|
73
193
|
## References
|
74
194
|
|
@@ -76,6 +196,15 @@ By `using AIXM::Refinements` you get the following general purpose methods:
|
|
76
196
|
* [AIXM on Wikipedia](https://en.wikipedia.org/wiki/AIXM)
|
77
197
|
* [Open Flightmaps](https://openflightmaps.org)
|
78
198
|
|
199
|
+
## Tests
|
200
|
+
|
201
|
+
Some tests are very time consuming and therefore skipped by default. To run the
|
202
|
+
full test suite, set the environment variable:
|
203
|
+
|
204
|
+
```
|
205
|
+
export SPEC_SCOPE=all
|
206
|
+
```
|
207
|
+
|
79
208
|
## Development
|
80
209
|
|
81
210
|
To install the development dependencies and then run the test suite:
|
data/aixm.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ['ruby@bitcetera.com']
|
11
11
|
spec.description = %q(Aeronautical Information Exchange Model (AIXM 4.5).)
|
12
12
|
spec.summary = %q(Aeronautical Information Exchange Model (AIXM 4.5).)
|
13
|
-
spec.homepage = '
|
13
|
+
spec.homepage = 'https://github.com/svoop/aixm'
|
14
14
|
spec.license = 'MIT'
|
15
15
|
|
16
16
|
spec.files = `git ls-files`.split($/)
|
@@ -18,6 +18,8 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
|
+
spec.required_ruby_version = '>= 2.5'
|
22
|
+
|
21
23
|
spec.add_development_dependency 'bundler'
|
22
24
|
spec.add_development_dependency 'rake'
|
23
25
|
spec.add_development_dependency 'minitest'
|
data/lib/aixm.rb
CHANGED
@@ -6,20 +6,22 @@ require 'digest'
|
|
6
6
|
require 'time'
|
7
7
|
|
8
8
|
require_relative 'aixm/version'
|
9
|
-
|
10
9
|
require_relative 'aixm/refinements'
|
11
10
|
|
11
|
+
require_relative 'aixm/document'
|
12
12
|
require_relative 'aixm/xy'
|
13
13
|
require_relative 'aixm/z'
|
14
|
-
require_relative 'aixm/geometry'
|
15
14
|
|
16
|
-
require_relative 'aixm/
|
17
|
-
require_relative 'aixm/
|
18
|
-
require_relative 'aixm/
|
19
|
-
require_relative 'aixm/
|
20
|
-
require_relative 'aixm/
|
21
|
-
|
22
|
-
require_relative 'aixm/
|
23
|
-
require_relative 'aixm/
|
15
|
+
require_relative 'aixm/component/base'
|
16
|
+
require_relative 'aixm/component/geometry'
|
17
|
+
require_relative 'aixm/component/geometry/point'
|
18
|
+
require_relative 'aixm/component/geometry/arc'
|
19
|
+
require_relative 'aixm/component/geometry/border'
|
20
|
+
require_relative 'aixm/component/geometry/circle'
|
21
|
+
require_relative 'aixm/component/class_layer'
|
22
|
+
require_relative 'aixm/component/vertical_limits'
|
23
|
+
require_relative 'aixm/component/schedule'
|
24
24
|
|
25
25
|
require_relative 'aixm/feature/airspace'
|
26
|
+
|
27
|
+
require_relative 'aixm/shortcuts'
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module AIXM
|
2
|
+
module Component
|
3
|
+
|
4
|
+
##
|
5
|
+
# Class layers consists of an optional airspace class and mandatory
|
6
|
+
# vertical limits.
|
7
|
+
class ClassLayer < Base
|
8
|
+
using AIXM::Refinements
|
9
|
+
|
10
|
+
CLASSES = %i(A B C D E F G)
|
11
|
+
|
12
|
+
attr_reader :vertical_limits
|
13
|
+
|
14
|
+
def initialize(class: nil, vertical_limits:)
|
15
|
+
@klass, @vertical_limits = binding.local_variable_get(:class)&.to_sym, vertical_limits
|
16
|
+
fail(ArgumentError, "invalid class `#{@klass}'") unless @klass.nil? || CLASSES.include?(@klass)
|
17
|
+
fail(ArgumentError, "invalid vertical limits") unless @vertical_limits.is_a? AIXM::Component::VerticalLimits
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Read the airspace class
|
22
|
+
#
|
23
|
+
# This and other workarounds in the initializer are necessary due to "class"
|
24
|
+
# being a reserved keyword in Ruby.
|
25
|
+
def class
|
26
|
+
@klass
|
27
|
+
end
|
28
|
+
|
29
|
+
##
|
30
|
+
# Digest to identify the payload
|
31
|
+
def to_digest
|
32
|
+
[self.class, vertical_limits.to_digest].to_digest
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Render AIXM
|
37
|
+
#
|
38
|
+
# Extensions:
|
39
|
+
# * +:OFM+ - Open Flightmaps
|
40
|
+
def to_xml(*extensions)
|
41
|
+
builder = Builder::XmlMarkup.new(indent: 2)
|
42
|
+
builder.codeClass(self.class.to_s) if self.class
|
43
|
+
builder << vertical_limits.to_xml(*extensions)
|
44
|
+
builder.target! # see https://github.com/jimweirich/builder/issues/42
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module AIXM
|
2
|
+
module Component
|
3
|
+
|
4
|
+
##
|
5
|
+
# Geometries define a 3D airspace horizontally. It's either exactly one
|
6
|
+
# circle or at least three points, arcs and borders (the last of which
|
7
|
+
# has to be a point with the same coordinates as the first).
|
8
|
+
#
|
9
|
+
# Example 1:
|
10
|
+
# geometry = AIXM.geometry(
|
11
|
+
# AIXM.point(...),
|
12
|
+
# AIXM.point(...)
|
13
|
+
# )
|
14
|
+
#
|
15
|
+
# Example 2:
|
16
|
+
# geometry = AIXM.geometry
|
17
|
+
# geometry << AIXM.point(...)
|
18
|
+
# geometry << AIXM.point(...)
|
19
|
+
class Geometry < Base
|
20
|
+
include Enumerable
|
21
|
+
extend Forwardable
|
22
|
+
using AIXM::Refinements
|
23
|
+
|
24
|
+
def_delegators :@result_array, :each, :<<
|
25
|
+
|
26
|
+
def initialize(*segments)
|
27
|
+
@result_array = segments
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# Array of +AIXM::Component::Geometry::...+ objects
|
32
|
+
def segments
|
33
|
+
@result_array
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
# Check whether the geometry is complete
|
38
|
+
def complete?
|
39
|
+
circle? || closed_shape?
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# Digest to identify the payload
|
44
|
+
def to_digest
|
45
|
+
segments.map(&:to_digest).to_digest
|
46
|
+
end
|
47
|
+
|
48
|
+
##
|
49
|
+
# Render AIXM
|
50
|
+
#
|
51
|
+
# Extensions:
|
52
|
+
# * +:OFM+ - Open Flightmaps
|
53
|
+
def to_xml(*extensions)
|
54
|
+
@result_array.map { |h| h.to_xml(*extensions) }.join
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def circle?
|
60
|
+
@result_array.size == 1 &&
|
61
|
+
@result_array.first.is_a?(AIXM::Component::Geometry::Circle)
|
62
|
+
end
|
63
|
+
|
64
|
+
def closed_shape?
|
65
|
+
@result_array.size >= 3 &&
|
66
|
+
!@result_array.any? { |h| h.is_a?(AIXM::Component::Geometry::Circle) } &&
|
67
|
+
@result_array.last.is_a?(AIXM::Component::Geometry::Point) &&
|
68
|
+
@result_array.first.xy == @result_array.last.xy
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|