aixm 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/CHANGELOG.md +14 -0
- data/Gemfile +3 -0
- data/Guardfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +100 -0
- data/Rakefile +12 -0
- data/aixm.gemspec +32 -0
- data/lib/aixm.rb +25 -0
- data/lib/aixm/constants.rb +6 -0
- data/lib/aixm/document.rb +65 -0
- data/lib/aixm/feature/airspace.rb +74 -0
- data/lib/aixm/geometry.rb +71 -0
- data/lib/aixm/horizontal/arc.rb +50 -0
- data/lib/aixm/horizontal/border.rb +45 -0
- data/lib/aixm/horizontal/circle.rb +53 -0
- data/lib/aixm/horizontal/point.rb +39 -0
- data/lib/aixm/refinements.rb +61 -0
- data/lib/aixm/schemas/4.5/AIXM-DataTypes.xsd +5231 -0
- data/lib/aixm/schemas/4.5/AIXM-Features.xsd +10066 -0
- data/lib/aixm/schemas/4.5/AIXM-Snapshot.xsd +352 -0
- data/lib/aixm/version.rb +3 -0
- data/lib/aixm/vertical/limits.rb +59 -0
- data/lib/aixm/xy.rb +52 -0
- data/lib/aixm/z.rb +39 -0
- data/spec/factory.rb +66 -0
- data/spec/lib/aixm/document_spec.rb +211 -0
- data/spec/lib/aixm/feature/airspace_spec.rb +96 -0
- data/spec/lib/aixm/geometry_spec.rb +218 -0
- data/spec/lib/aixm/horizontal/arc_spec.rb +69 -0
- data/spec/lib/aixm/horizontal/border_spec.rb +47 -0
- data/spec/lib/aixm/horizontal/circle_spec.rb +65 -0
- data/spec/lib/aixm/horizontal/point_spec.rb +42 -0
- data/spec/lib/aixm/refinements_spec.rb +180 -0
- data/spec/lib/aixm/version_spec.rb +7 -0
- data/spec/lib/aixm/vertical/limits_spec.rb +78 -0
- data/spec/lib/aixm/xy_spec.rb +131 -0
- data/spec/lib/aixm/z_spec.rb +59 -0
- data/spec/sounds/failure.mp3 +0 -0
- data/spec/sounds/success.mp3 +0 -0
- data/spec/spec_helper.rb +28 -0
- metadata +243 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 153468c1338fc26792178d856c438511fa10ac58988ef0e938980fd590338164
|
4
|
+
data.tar.gz: b04ae1dcbe0ef0d90beea492c08d08aeab943a156127c70cdc94c5ec69b4995b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 45a95906e65595273f9e5667a7aee0498f5390a6d9c86500f00dafbc080376316fa4b8d062deefda840ec9a0d403ab941762c59f4b4d413eed17868102e86196
|
7
|
+
data.tar.gz: efe2127226e7a3e3d5b25f69bb29688fa12c59b1af579a272291aa200b5b2447c24b4093e248eb671ca0cb915a0aa31a50f757c8dcb5770f3b7d28139ab78396
|
data/.gitignore
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.5.0
|
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Sven Schwyn
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
[![Version](https://img.shields.io/gem/v/aixm.svg?style=flat)](https://rubygems.org/gems/aixm)
|
2
|
+
[![Continuous Integration](https://img.shields.io/travis/svoop/aixm/master.svg?style=flat)](https://travis-ci.org/svoop/aixm)
|
3
|
+
[![Code Climate](https://img.shields.io/codeclimate/github/svoop/aixm.svg?style=flat)](https://codeclimate.com/github/svoop/aixm)
|
4
|
+
[![Gitter](https://img.shields.io/gitter/room/svoop/aixm.svg?style=flat)](https://gitter.im/svoop/aixm)
|
5
|
+
[![Donorbox](https://img.shields.io/badge/donate-on_donorbox-yellow.svg)](https://donorbox.org/bitcetera-aixm)
|
6
|
+
|
7
|
+
# AIXM
|
8
|
+
|
9
|
+
Partial implementation of the [Aeronautical Information Exchange Model (AIXM 4.5)](http://aixm.aero)
|
10
|
+
for Ruby.
|
11
|
+
|
12
|
+
For now, only the parts needed to automize the AIP import of [Open Flightmaps](https://openflightmaps.org)
|
13
|
+
are part of this gem. Most notably, the gem is only a builder of AIXM 4.5
|
14
|
+
snapshot files and does not parse them.
|
15
|
+
|
16
|
+
* [Homepage](https://github.com/svoop/aixm)
|
17
|
+
* Author: [Sven Schwyn - Bitcetera](http://www.bitcetera.com)
|
18
|
+
|
19
|
+
## Install
|
20
|
+
|
21
|
+
Add this to your <tt>Gemfile</tt>:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
gem aixm
|
25
|
+
```
|
26
|
+
|
27
|
+
## Usage
|
28
|
+
|
29
|
+
### Types
|
30
|
+
|
31
|
+
#### Coordinate
|
32
|
+
|
33
|
+
All of the below are equivalent:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
AIXM::XY.new(lat: %q(11°22'33.44"), long: %q(-111°22'33.44"))
|
37
|
+
AIXM::XY.new(lat: '112233.44N', long: '1112233.44W')
|
38
|
+
AIXM::XY.new(lat: 11.375955555555556, long: -111.37595555555555)
|
39
|
+
```
|
40
|
+
|
41
|
+
#### Altitude
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
AIXM::Z.new(alt: 1000, code: :QFE) # height: 1000ft above ground
|
45
|
+
AIXM::Z.new(alt: 2000, code: :QNH) # altitude: of 2000ft above mean sea level
|
46
|
+
AIXM::Z.new(alt: 45, code: :QNE) # altitude: flight level 45
|
47
|
+
```
|
48
|
+
|
49
|
+
### Document
|
50
|
+
|
51
|
+
See <tt>spec/factory.rb</tt> for examples.
|
52
|
+
|
53
|
+
## Rendering
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
document.to_xml # render AIXM 4.5 compliant XML
|
57
|
+
document.to_xml(:OFM) # render AIXM 4.5 + OFM extensions XML
|
58
|
+
```
|
59
|
+
|
60
|
+
## Constants
|
61
|
+
|
62
|
+
* <tt>AIXM::GROUND</tt> - height: 0ft above ground
|
63
|
+
|
64
|
+
## Refinements
|
65
|
+
|
66
|
+
By `using AIXM::Refinements` you get the following general purpose methods:
|
67
|
+
|
68
|
+
* <tt>String#indent(number)</tt><br>Indent every line of a string with *number* spaces
|
69
|
+
* <tt>String#to_dd</tt><br>Convert DMS angle to DD or <tt>nil</tt> if the format is not recognized
|
70
|
+
* <tt>Float#to_dms(padding)</tt><br>Convert DD angle to DMS with the degrees zero padded to *padding* length
|
71
|
+
* <tt>Float#trim</tt><br>Convert whole numbers to Integer and leave all other untouched
|
72
|
+
|
73
|
+
## References
|
74
|
+
|
75
|
+
* [AIXM](http://aixm.aero)
|
76
|
+
* [AIXM on Wikipedia](https://en.wikipedia.org/wiki/AIXM)
|
77
|
+
* [Open Flightmaps](https://openflightmaps.org)
|
78
|
+
|
79
|
+
## Development
|
80
|
+
|
81
|
+
To install the development dependencies and then run the test suite:
|
82
|
+
|
83
|
+
```
|
84
|
+
bundle install
|
85
|
+
bundle exec rake # run tests once
|
86
|
+
bundle exec guard # run tests whenever files are modified
|
87
|
+
```
|
88
|
+
|
89
|
+
Please submit issues on:
|
90
|
+
|
91
|
+
https://github.com/svoop/aixm/issues
|
92
|
+
|
93
|
+
To contribute code, fork the project on Github, add your code and submit a
|
94
|
+
pull request:
|
95
|
+
|
96
|
+
https://help.github.com/articles/fork-a-repo
|
97
|
+
|
98
|
+
## License
|
99
|
+
|
100
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/aixm.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'aixm/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'aixm'
|
8
|
+
spec.version = AIXM::VERSION
|
9
|
+
spec.authors = ['Sven Schwyn']
|
10
|
+
spec.email = ['ruby@bitcetera.com']
|
11
|
+
spec.description = %q(Aeronautical Information Exchange Model (AIXM 4.5).)
|
12
|
+
spec.summary = %q(Aeronautical Information Exchange Model (AIXM 4.5).)
|
13
|
+
spec.homepage = 'http://www.bitcetera.com/products/aixm'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_development_dependency 'bundler'
|
22
|
+
spec.add_development_dependency 'rake'
|
23
|
+
spec.add_development_dependency 'minitest'
|
24
|
+
spec.add_development_dependency 'minitest-reporters'
|
25
|
+
spec.add_development_dependency 'minitest-sound'
|
26
|
+
spec.add_development_dependency 'minitest-matchers'
|
27
|
+
spec.add_development_dependency 'guard'
|
28
|
+
spec.add_development_dependency 'guard-minitest'
|
29
|
+
|
30
|
+
spec.add_runtime_dependency 'builder', '~> 3'
|
31
|
+
spec.add_runtime_dependency 'nokogiri', '~> 1'
|
32
|
+
end
|
data/lib/aixm.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'builder'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'forwardable'
|
4
|
+
require 'ostruct'
|
5
|
+
require 'digest'
|
6
|
+
require 'time'
|
7
|
+
|
8
|
+
require_relative 'aixm/version'
|
9
|
+
|
10
|
+
require_relative 'aixm/refinements'
|
11
|
+
|
12
|
+
require_relative 'aixm/xy'
|
13
|
+
require_relative 'aixm/z'
|
14
|
+
require_relative 'aixm/geometry'
|
15
|
+
|
16
|
+
require_relative 'aixm/horizontal/point'
|
17
|
+
require_relative 'aixm/horizontal/arc'
|
18
|
+
require_relative 'aixm/horizontal/border'
|
19
|
+
require_relative 'aixm/horizontal/circle'
|
20
|
+
require_relative 'aixm/vertical/limits'
|
21
|
+
|
22
|
+
require_relative 'aixm/constants'
|
23
|
+
require_relative 'aixm/document'
|
24
|
+
|
25
|
+
require_relative 'aixm/feature/airspace'
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module AIXM
|
2
|
+
class Document
|
3
|
+
|
4
|
+
include Enumerable
|
5
|
+
extend Forwardable
|
6
|
+
using AIXM::Refinements
|
7
|
+
|
8
|
+
def_delegators :@result_array, :each, :<<
|
9
|
+
|
10
|
+
attr_reader :created_at, :effective_at
|
11
|
+
|
12
|
+
##
|
13
|
+
# Define a AIXM-Snapshot document
|
14
|
+
#
|
15
|
+
# Options:
|
16
|
+
# * +created_at+ - creation date (default: now)
|
17
|
+
# * +effective_at+ - snapshot effective after date (default: now)
|
18
|
+
def initialize(created_at: nil, effective_at: nil)
|
19
|
+
@created_at, @effective_at = created_at, effective_at
|
20
|
+
@result_array = []
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# Array of features defined by this document
|
25
|
+
def features
|
26
|
+
@result_array
|
27
|
+
end
|
28
|
+
|
29
|
+
##
|
30
|
+
# Validate against the XSD and return an array of errors
|
31
|
+
def errors
|
32
|
+
xsd = Nokogiri::XML::Schema(File.open(AIXM::SCHEMA))
|
33
|
+
xsd.validate(Nokogiri::XML(to_xml))
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
# Check whether the document is valid (extensions excluded)
|
38
|
+
def valid?
|
39
|
+
any? && reduce(true) { |b, f| b && f.valid? } && errors.none?
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# Render AIXM
|
44
|
+
#
|
45
|
+
# Extensions:
|
46
|
+
# * +:OFM+ - Open Flightmaps
|
47
|
+
def to_xml(*extensions)
|
48
|
+
now = Time.now.xmlschema
|
49
|
+
meta = {
|
50
|
+
'xmlns:xsi': 'http://www.aixm.aero/schema/4.5/AIXM-Snapshot.xsd',
|
51
|
+
version: '4.5',
|
52
|
+
origin: "AIXM #{AIXM::VERSION} Ruby gem",
|
53
|
+
created: @created_at&.xmlschema || now,
|
54
|
+
effective: @effective_at&.xmlschema || now
|
55
|
+
}
|
56
|
+
meta[:version] += ' + OFM extensions of version 0.1' if extensions.include?(:OFM)
|
57
|
+
builder = Builder::XmlMarkup.new(indent: 2)
|
58
|
+
builder.instruct!
|
59
|
+
builder.tag!('AIXM-Snapshot', meta) do |aixm_snapshot|
|
60
|
+
aixm_snapshot << @result_array.map { |f| f.to_xml(extensions) }.join.indent(2)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module AIXM
|
2
|
+
module Feature
|
3
|
+
class Airspace
|
4
|
+
|
5
|
+
using AIXM::Refinements
|
6
|
+
|
7
|
+
attr_reader :name, :type
|
8
|
+
attr_reader :vertical_limits
|
9
|
+
attr_accessor :geometry, :remarks
|
10
|
+
|
11
|
+
##
|
12
|
+
# Airspace feature
|
13
|
+
#
|
14
|
+
# Options:
|
15
|
+
# * +name+ - name of the airspace (will be converted to uppercase)
|
16
|
+
# * +type+ - airspace type (e.g. +TMA+ or +P+)
|
17
|
+
def initialize(name:, type:)
|
18
|
+
@geometry = AIXM::Geometry.new
|
19
|
+
@name, @type = name.upcase, type
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# Assign a +Vertical::Limits+ object
|
24
|
+
def vertical_limits=(value)
|
25
|
+
fail(ArgumentError, "invalid vertical limit") unless value.is_a?(AIXM::Vertical::Limits)
|
26
|
+
@vertical_limits = value
|
27
|
+
end
|
28
|
+
|
29
|
+
##
|
30
|
+
# Check whether the airspace is valid
|
31
|
+
def valid?
|
32
|
+
name && type && vertical_limits && geometry.valid?
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Digest to identify the payload
|
37
|
+
def to_digest
|
38
|
+
[name, type, vertical_limits.to_digest, geometry.to_digest, remarks].to_digest
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Render AIXM
|
43
|
+
#
|
44
|
+
# Extensions:
|
45
|
+
# * +:OFM+ - Open Flightmaps
|
46
|
+
def to_xml(*extensions)
|
47
|
+
mid = to_digest
|
48
|
+
builder = Builder::XmlMarkup.new(indent: 2)
|
49
|
+
builder.Ase(extensions.include?(:OFM) ? { xt_classLayersAvail: false } : {}) do |ase|
|
50
|
+
ase.AseUid(extensions.include?(:OFM) ? { mid: mid, newEntity: true } : { mid: mid }) do |aseuid|
|
51
|
+
aseuid.codeType(type)
|
52
|
+
aseuid.codeId(mid) # TODO: verify
|
53
|
+
end
|
54
|
+
ase.txtName(name)
|
55
|
+
ase << vertical_limits.to_xml(extensions).indent(2)
|
56
|
+
ase.txtRmk(remarks) if remarks
|
57
|
+
if extensions.include?(:OFM)
|
58
|
+
ase.xt_txtRmk(remarks)
|
59
|
+
ase.xt_selAvail(false)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
builder.Abd do |abd|
|
63
|
+
abd.AbdUid do |abduid|
|
64
|
+
abduid.AseUid(extensions.include?(:OFM) ? { mid: mid, newEntity: true } : { mid: mid }) do |aseuid|
|
65
|
+
aseuid.codeType(type)
|
66
|
+
aseuid.codeId(mid) # TODO: verify
|
67
|
+
end
|
68
|
+
end
|
69
|
+
abd << geometry.to_xml(extensions).indent(2)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module AIXM
|
2
|
+
class Geometry
|
3
|
+
|
4
|
+
include Enumerable
|
5
|
+
extend Forwardable
|
6
|
+
using AIXM::Refinements
|
7
|
+
|
8
|
+
def_delegators :@result_array, :each, :<<
|
9
|
+
|
10
|
+
##
|
11
|
+
# Define a shape (horizontal geometry) which is either exactly one
|
12
|
+
# +AIXM::Horizontals::Circle+ or any number of +AIXM::Horizontals::Point+,
|
13
|
+
# +::Arc+ and +::Border+.
|
14
|
+
#
|
15
|
+
# Example 1:
|
16
|
+
# geometry = AIXM::Geometry.new(
|
17
|
+
# AIXM::Horizontals::Point(...),
|
18
|
+
# AIXM::Horizontals::Point(...)
|
19
|
+
# )
|
20
|
+
#
|
21
|
+
# Example 2:
|
22
|
+
# geometry = AIXM::Geometry.new
|
23
|
+
# geometry << AIXM::Horizontals::Point(...)
|
24
|
+
# geometry << AIXM::Horizontals::Point(...)
|
25
|
+
def initialize(*horizontals)
|
26
|
+
@result_array = horizontals
|
27
|
+
end
|
28
|
+
|
29
|
+
##
|
30
|
+
# Array of +AIXM::Horizontal::...+ objects
|
31
|
+
def horizontals
|
32
|
+
@result_array
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Check whether the geometry is valid
|
37
|
+
def valid?
|
38
|
+
circle? || closed_shape?
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Digest to identify the payload
|
43
|
+
def to_digest
|
44
|
+
horizontals.map(&:to_digest).to_digest
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# Render AIXM
|
49
|
+
#
|
50
|
+
# Extensions:
|
51
|
+
# * +:OFM+ - Open Flightmaps
|
52
|
+
def to_xml(*extensions)
|
53
|
+
@result_array.map { |h| h.to_xml(extensions) }.join
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def circle?
|
59
|
+
@result_array.size == 1 &&
|
60
|
+
@result_array.first.is_a?(AIXM::Horizontal::Circle)
|
61
|
+
end
|
62
|
+
|
63
|
+
def closed_shape?
|
64
|
+
@result_array.size >= 3 &&
|
65
|
+
!@result_array.any? { |h| h.is_a?(AIXM::Horizontal::Circle) } &&
|
66
|
+
@result_array.last.is_a?(AIXM::Horizontal::Point) &&
|
67
|
+
@result_array.first.xy == @result_array.last.xy
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|