aixm 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +5 -0
  5. data/CHANGELOG.md +14 -0
  6. data/Gemfile +3 -0
  7. data/Guardfile +7 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +100 -0
  10. data/Rakefile +12 -0
  11. data/aixm.gemspec +32 -0
  12. data/lib/aixm.rb +25 -0
  13. data/lib/aixm/constants.rb +6 -0
  14. data/lib/aixm/document.rb +65 -0
  15. data/lib/aixm/feature/airspace.rb +74 -0
  16. data/lib/aixm/geometry.rb +71 -0
  17. data/lib/aixm/horizontal/arc.rb +50 -0
  18. data/lib/aixm/horizontal/border.rb +45 -0
  19. data/lib/aixm/horizontal/circle.rb +53 -0
  20. data/lib/aixm/horizontal/point.rb +39 -0
  21. data/lib/aixm/refinements.rb +61 -0
  22. data/lib/aixm/schemas/4.5/AIXM-DataTypes.xsd +5231 -0
  23. data/lib/aixm/schemas/4.5/AIXM-Features.xsd +10066 -0
  24. data/lib/aixm/schemas/4.5/AIXM-Snapshot.xsd +352 -0
  25. data/lib/aixm/version.rb +3 -0
  26. data/lib/aixm/vertical/limits.rb +59 -0
  27. data/lib/aixm/xy.rb +52 -0
  28. data/lib/aixm/z.rb +39 -0
  29. data/spec/factory.rb +66 -0
  30. data/spec/lib/aixm/document_spec.rb +211 -0
  31. data/spec/lib/aixm/feature/airspace_spec.rb +96 -0
  32. data/spec/lib/aixm/geometry_spec.rb +218 -0
  33. data/spec/lib/aixm/horizontal/arc_spec.rb +69 -0
  34. data/spec/lib/aixm/horizontal/border_spec.rb +47 -0
  35. data/spec/lib/aixm/horizontal/circle_spec.rb +65 -0
  36. data/spec/lib/aixm/horizontal/point_spec.rb +42 -0
  37. data/spec/lib/aixm/refinements_spec.rb +180 -0
  38. data/spec/lib/aixm/version_spec.rb +7 -0
  39. data/spec/lib/aixm/vertical/limits_spec.rb +78 -0
  40. data/spec/lib/aixm/xy_spec.rb +131 -0
  41. data/spec/lib/aixm/z_spec.rb +59 -0
  42. data/spec/sounds/failure.mp3 +0 -0
  43. data/spec/sounds/success.mp3 +0 -0
  44. data/spec/spec_helper.rb +28 -0
  45. metadata +243 -0
@@ -0,0 +1,69 @@
1
+ require_relative '../../../spec_helper'
2
+
3
+ describe AIXM::Horizontal::Arc do
4
+ describe :initialize do
5
+ it "won't accept invalid arguments" do
6
+ xy = AIXM::XY.new(lat: 11.1, long: 22.2)
7
+ -> { AIXM::Horizontal::Arc.new(xy: 0, center_xy: xy, clockwise: true) }.must_raise ArgumentError
8
+ -> { AIXM::Horizontal::Arc.new(xy: xy, center_xy: 0, clockwise: true) }.must_raise ArgumentError
9
+ -> { AIXM::Horizontal::Arc.new(xy: xy, center_xy: xy, clockwise: 0) }.must_raise ArgumentError
10
+ end
11
+ end
12
+
13
+ describe :clockwise? do
14
+ it "must return true or false" do
15
+ xy = AIXM::XY.new(lat: 11.1, long: 22.2)
16
+ AIXM::Horizontal::Arc.new(xy: xy, center_xy: xy, clockwise: true).must_be :clockwise?
17
+ AIXM::Horizontal::Arc.new(xy: xy, center_xy: xy, clockwise: false).wont_be :clockwise?
18
+ end
19
+ end
20
+
21
+ describe :to_digest do
22
+ it "must return digest of payload" do
23
+ subject = AIXM::Horizontal::Arc.new(
24
+ xy: AIXM::XY.new(lat: 11.1, long: 33.3),
25
+ center_xy: AIXM::XY.new(lat: 22.2, long: 33.3),
26
+ clockwise: true
27
+ )
28
+ subject.to_digest.must_equal '35B2E1AF'
29
+ end
30
+ end
31
+
32
+ describe :to_xml do
33
+ it "must build correct XML for clockwise arcs" do
34
+ subject = AIXM::Horizontal::Arc.new(
35
+ xy: AIXM::XY.new(lat: 11.1, long: 33.3),
36
+ center_xy: AIXM::XY.new(lat: 22.2, long: 33.3),
37
+ clockwise: true
38
+ )
39
+ subject.to_xml.must_equal <<~END
40
+ <Avx>
41
+ <codeType>CWA</codeType>
42
+ <geoLat>110600.00N</geoLat>
43
+ <geoLong>0331800.00E</geoLong>
44
+ <codeDatum>WGE</codeDatum>
45
+ <geoLatArc>221200.00N</geoLatArc>
46
+ <geoLongArc>0331800.00E</geoLongArc>
47
+ </Avx>
48
+ END
49
+ end
50
+
51
+ it "must build correct XML for counter-clockwise arcs" do
52
+ subject = AIXM::Horizontal::Arc.new(
53
+ xy: AIXM::XY.new(lat: 11.1, long: 33.3),
54
+ center_xy: AIXM::XY.new(lat: 22.2, long: 33.3),
55
+ clockwise: false
56
+ )
57
+ subject.to_xml.must_equal <<~END
58
+ <Avx>
59
+ <codeType>CCA</codeType>
60
+ <geoLat>110600.00N</geoLat>
61
+ <geoLong>0331800.00E</geoLong>
62
+ <codeDatum>WGE</codeDatum>
63
+ <geoLatArc>221200.00N</geoLatArc>
64
+ <geoLongArc>0331800.00E</geoLongArc>
65
+ </Avx>
66
+ END
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,47 @@
1
+ require_relative '../../../spec_helper'
2
+
3
+ describe AIXM::Horizontal::Border do
4
+ describe :to_digest do
5
+ it "must return digest of payload" do
6
+ subject = AIXM::Horizontal::Border.new(
7
+ xy: AIXM::XY.new(lat: 11.1, long: 22.2),
8
+ name: 'foobar',
9
+ name_mid: 123
10
+ )
11
+ subject.to_digest.must_equal '8955450F'
12
+ end
13
+ end
14
+
15
+ describe :to_xml do
16
+ it "must build correct XML with name_mid" do
17
+ subject = AIXM::Horizontal::Border.new(
18
+ xy: AIXM::XY.new(lat: 11.1, long: 22.2),
19
+ name: 'foobar',
20
+ name_mid: 123
21
+ )
22
+ subject.to_xml.must_equal <<~END
23
+ <Avx>
24
+ <codeType>FNT</codeType>
25
+ <geoLat>110600.00N</geoLat>
26
+ <geoLong>0221200.00E</geoLong>
27
+ <codeDatum>WGE</codeDatum>
28
+ </Avx>
29
+ END
30
+ end
31
+
32
+ it "must build correct XML without name_mid" do
33
+ subject = AIXM::Horizontal::Border.new(
34
+ xy: AIXM::XY.new(lat: 11.1, long: 22.2),
35
+ name: 'foobar'
36
+ )
37
+ subject.to_xml.must_equal <<~END
38
+ <Avx>
39
+ <codeType>FNT</codeType>
40
+ <geoLat>110600.00N</geoLat>
41
+ <geoLong>0221200.00E</geoLong>
42
+ <codeDatum>WGE</codeDatum>
43
+ </Avx>
44
+ END
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,65 @@
1
+ require_relative '../../../spec_helper'
2
+
3
+ describe AIXM::Horizontal::Circle do
4
+ describe :initialize do
5
+ it "won't accept invalid arguments" do
6
+ -> { AIXM::Horizontal::Circle.new(center_xy: 0, radius: 0) }.must_raise ArgumentError
7
+ end
8
+ end
9
+
10
+ describe :north_xy do
11
+ it "must calculate approximation of northmost point on the circumference" do
12
+ subject = AIXM::Horizontal::Circle.new(
13
+ center_xy: AIXM::XY.new(lat: 12.12345678, long: -23.12345678),
14
+ radius: 15
15
+ )
16
+ subject.send(:north_xy).must_equal AIXM::XY.new(lat: 12.25835502, long: -23.12345678)
17
+ end
18
+ end
19
+
20
+ describe :to_digest do
21
+ it "must return digest of payload" do
22
+ subject = AIXM::Horizontal::Circle.new(
23
+ center_xy: AIXM::XY.new(lat: 12.12345678, long: -23.12345678),
24
+ radius: 15
25
+ )
26
+ subject.to_digest.must_equal '914C5F08'
27
+ end
28
+ end
29
+
30
+ describe :to_xml do
31
+ it "must build correct XML for circles not near the equator" do
32
+ subject = AIXM::Horizontal::Circle.new(
33
+ center_xy: AIXM::XY.new(lat: 11.1, long: 22.2),
34
+ radius: 25
35
+ )
36
+ subject.to_xml.must_equal <<~END
37
+ <Avx>
38
+ <codeType>CWA</codeType>
39
+ <geoLat>111929.39N</geoLat>
40
+ <geoLong>0221200.00E</geoLong>
41
+ <codeDatum>WGE</codeDatum>
42
+ <geoLatArc>110600.00N</geoLatArc>
43
+ <geoLongArc>0221200.00E</geoLongArc>
44
+ </Avx>
45
+ END
46
+ end
47
+
48
+ it "must build correct XML for circles near the equator" do
49
+ subject = AIXM::Horizontal::Circle.new(
50
+ center_xy: AIXM::XY.new(lat: -0.0005, long: -22.2),
51
+ radius: 50
52
+ )
53
+ subject.to_xml.must_equal <<~END
54
+ <Avx>
55
+ <codeType>CWA</codeType>
56
+ <geoLat>002656.98N</geoLat>
57
+ <geoLong>0221200.00W</geoLong>
58
+ <codeDatum>WGE</codeDatum>
59
+ <geoLatArc>000001.80S</geoLatArc>
60
+ <geoLongArc>0221200.00W</geoLongArc>
61
+ </Avx>
62
+ END
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,42 @@
1
+ require_relative '../../../spec_helper'
2
+
3
+ describe AIXM::Horizontal::Point do
4
+ describe :initialize do
5
+ it "won't accept invalid arguments" do
6
+ -> { AIXM::Horizontal::Point.new(xy: 0) }.must_raise ArgumentError
7
+ end
8
+ end
9
+
10
+ describe :to_digest do
11
+ it "must return digest of payload" do
12
+ subject = AIXM::Horizontal::Point.new(xy: AIXM::XY.new(lat: 11.1, long: 22.2))
13
+ subject.to_digest.must_equal '215D7CBA'
14
+ end
15
+ end
16
+
17
+ describe :to_xml do
18
+ it "must build correct XML for N/E points" do
19
+ subject = AIXM::Horizontal::Point.new(xy: AIXM::XY.new(lat: 11.1, long: 22.2))
20
+ subject.to_xml.must_equal <<~END
21
+ <Avx>
22
+ <codeType>GRC</codeType>
23
+ <geoLat>110600.00N</geoLat>
24
+ <geoLong>0221200.00E</geoLong>
25
+ <codeDatum>WGE</codeDatum>
26
+ </Avx>
27
+ END
28
+ end
29
+
30
+ it "must build correct XML for S/W points" do
31
+ subject = AIXM::Horizontal::Point.new(xy: AIXM::XY.new(lat: -11.1, long: -22.2))
32
+ subject.to_xml.must_equal <<~END
33
+ <Avx>
34
+ <codeType>GRC</codeType>
35
+ <geoLat>110600.00S</geoLat>
36
+ <geoLong>0221200.00W</geoLong>
37
+ <codeDatum>WGE</codeDatum>
38
+ </Avx>
39
+ END
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,180 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ using AIXM::Refinements
4
+
5
+ describe AIXM::Refinements do
6
+
7
+ describe 'Array#to_digest' do
8
+ it "must digest single string" do
9
+ %w(a).to_digest.must_equal Digest::MD5.hexdigest('a')[0, 8].upcase
10
+ end
11
+
12
+ it "must digest double string" do
13
+ %w(a b).to_digest.must_equal Digest::MD5.hexdigest('a|b')[0, 8].upcase
14
+ end
15
+
16
+ it "must digest integer" do
17
+ [5].to_digest.must_equal Digest::MD5.hexdigest('5')[0, 8].upcase
18
+ end
19
+
20
+ it "must digest float" do
21
+ [5.0].to_digest.must_equal Digest::MD5.hexdigest('5.0')[0, 8].upcase
22
+ end
23
+
24
+ it "must digest boolean" do
25
+ [true, false].to_digest.must_equal Digest::MD5.hexdigest('true|false')[0, 8].upcase
26
+ end
27
+
28
+ it "must digest nil" do
29
+ [nil].to_digest.must_equal Digest::MD5.hexdigest('')[0, 8].upcase
30
+ end
31
+ end
32
+
33
+ describe 'String#indent' do
34
+ it "must indent single line string" do
35
+ 'foobar'.indent(2).must_equal ' foobar'
36
+ end
37
+
38
+ it "must indent multi line string" do
39
+ "foo\nbar".indent(2).must_equal " foo\n bar"
40
+ "foo\nbar\n".indent(2).must_equal " foo\n bar\n"
41
+ end
42
+ end
43
+
44
+ describe 'String#to_dd' do
45
+ it "must convert +6.2 DMS to DD" do
46
+ %q(12°34'56.78").to_dd.must_equal 12.58243888888889
47
+ %q(12 34 56.78).to_dd.must_equal 12.58243888888889
48
+ %q(123456.78).to_dd.must_equal 12.58243888888889
49
+ end
50
+
51
+ it "must convert -6.2 DMS to DD" do
52
+ %q(-12°34'56.78").to_dd.must_equal(-12.58243888888889)
53
+ %q(-12 34 56.78).to_dd.must_equal(-12.58243888888889)
54
+ %q(-123456.78).to_dd.must_equal(-12.58243888888889)
55
+ end
56
+
57
+ it "must convert +7.2 DMS to DD" do
58
+ %q(111°22'33.44").to_dd.must_equal 111.37595555555555
59
+ %q(111 22 33.44).to_dd.must_equal 111.37595555555555
60
+ %q(1112233.44).to_dd.must_equal 111.37595555555555
61
+ end
62
+
63
+ it "must convert -7.2 DMS to DD" do
64
+ %q(-111°22'33.44").to_dd.must_equal(-111.37595555555555)
65
+ %q(-111 22 33.44).to_dd.must_equal(-111.37595555555555)
66
+ %q(-1112233.44).to_dd.must_equal(-111.37595555555555)
67
+ end
68
+
69
+ it "must convert +6.1 DMS to DD" do
70
+ %q(12°34'56.7").to_dd.must_equal 12.582416666666667
71
+ %q(12 34 56.7).to_dd.must_equal 12.582416666666667
72
+ %q(123456.7).to_dd.must_equal 12.582416666666667
73
+ end
74
+
75
+ it "must convert -6.1 DMS to DD" do
76
+ %q(-12°34'56.7").to_dd.must_equal(-12.582416666666667)
77
+ %q(-12 34 56.7).to_dd.must_equal(-12.582416666666667)
78
+ %q(-123456.7).to_dd.must_equal(-12.582416666666667)
79
+ end
80
+
81
+ it "must convert +7.1 DMS to DD" do
82
+ %q(111°22'33.4").to_dd.must_equal 111.37594444444444
83
+ %q(111 22 33.4).to_dd.must_equal 111.37594444444444
84
+ %q(1112233.4).to_dd.must_equal 111.37594444444444
85
+ end
86
+
87
+ it "must convert +7.1 DMS to DD" do
88
+ %q(-111°22'33.4").to_dd.must_equal(-111.37594444444444)
89
+ %q(-111 22 33.4).to_dd.must_equal(-111.37594444444444)
90
+ %q(-1112233.4).to_dd.must_equal(-111.37594444444444)
91
+ end
92
+
93
+ it "must convert +6.0 DMS to DD" do
94
+ %q(12°34'56").to_dd.must_equal 12.582222222222223
95
+ %q(12 34 56).to_dd.must_equal 12.582222222222223
96
+ %q(123456).to_dd.must_equal 12.582222222222223
97
+ end
98
+
99
+ it "must convert -6.0 DMS to DD" do
100
+ %q(-12°34'56").to_dd.must_equal(-12.582222222222223)
101
+ %q(-12 34 56).to_dd.must_equal(-12.582222222222223)
102
+ %q(-123456).to_dd.must_equal(-12.582222222222223)
103
+ end
104
+
105
+ it "must convert +7.0 DMS to DD" do
106
+ %q(111°22'33").to_dd.must_equal 111.37583333333333
107
+ %q(111 22 33).to_dd.must_equal 111.37583333333333
108
+ %q(1112233).to_dd.must_equal 111.37583333333333
109
+ end
110
+
111
+ it "must convert +7.0 DMS to DD" do
112
+ %q(-111°22'33").to_dd.must_equal(-111.37583333333333)
113
+ %q(-111 22 33).to_dd.must_equal(-111.37583333333333)
114
+ %q(-1112233).to_dd.must_equal(-111.37583333333333)
115
+ end
116
+
117
+ it "must do all possible roundtrip conversions" do
118
+ 2.times.with_index do |degrees|
119
+ 60.times.with_index do |minutes|
120
+ 60.times.with_index do |seconds|
121
+ 100.times.with_index do |fractions|
122
+ subject = %q(%03d°%02d'%02d.%02d") % [degrees, minutes, seconds, fractions]
123
+ subject.to_dd.to_dms.must_equal subject
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+
131
+ describe 'Float#to_dms' do
132
+ it "must convert +1. DD to DMS" do
133
+ 1.37595556.to_dms.must_equal %q(001°22'33.44")
134
+ end
135
+
136
+ it "must convert -1. DD to DMS" do
137
+ -1.37595556.to_dms.must_equal %q(-001°22'33.44")
138
+ end
139
+
140
+ it "must convert +2. DD to DMS" do
141
+ 11.37595556.to_dms.must_equal %q(011°22'33.44")
142
+ end
143
+
144
+ it "must convert -2. DD to DMS" do
145
+ -11.37595556.to_dms.must_equal %q(-011°22'33.44")
146
+ end
147
+
148
+ it "must convert +3. DD to DMS" do
149
+ 111.37595556.to_dms.must_equal %q(111°22'33.44")
150
+ end
151
+
152
+ it "must convert -3. DD to DMS" do
153
+ -111.37595556.to_dms.must_equal %q(-111°22'33.44")
154
+ end
155
+
156
+ it "must convert DD to DMS with degrees only" do
157
+ 11.0.to_dms.must_equal %q(011°00'00.00")
158
+ end
159
+
160
+ it "must convert DD to DMS with degrees and minutes only" do
161
+ 11.36666667.to_dms.must_equal %q(011°22'00.00")
162
+ end
163
+
164
+ it "must convert DD to DMS with tenth of seconds only" do
165
+ 1.37594444.to_dms.must_equal %q(001°22'33.40")
166
+ end
167
+
168
+ it "must convert DD to DMS with whole seconds only" do
169
+ 1.37583333.to_dms.must_equal %q(001°22'33.00")
170
+ end
171
+
172
+ it "must convert DD to two zero padded DMS" do
173
+ 1.37595556.to_dms(2).must_equal %q(01°22'33.44")
174
+ end
175
+
176
+ it "must convert DD to no zero padded DMS" do
177
+ 1.37595556.to_dms(0).must_equal %q(1°22'33.44")
178
+ end
179
+ end
180
+ end
@@ -0,0 +1,7 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe AIXM do
4
+ it "must be defined" do
5
+ AIXM::VERSION.wont_be_nil
6
+ end
7
+ end
@@ -0,0 +1,78 @@
1
+ require_relative '../../../spec_helper'
2
+
3
+ describe AIXM::Vertical::Limits do
4
+ describe :initialize do
5
+ it "won't accept invalid arguments" do
6
+ z = AIXM::Z.new(alt: 1000, code: :QNH)
7
+ -> { AIXM::Vertical::Limits.new(upper_z: 0, lower_z: z, max_z: z, min_z: z) }.must_raise ArgumentError
8
+ -> { AIXM::Vertical::Limits.new(upper_z: z, lower_z: 0, max_z: z, min_z: z) }.must_raise ArgumentError
9
+ -> { AIXM::Vertical::Limits.new(upper_z: z, lower_z: z, max_z: 0, min_z: z) }.must_raise ArgumentError
10
+ -> { AIXM::Vertical::Limits.new(upper_z: z, lower_z: z, max_z: z, min_z: 0) }.must_raise ArgumentError
11
+ end
12
+ end
13
+
14
+ describe :to_digest do
15
+ it "must return digest of payload" do
16
+ subject = AIXM::Vertical::Limits.new(
17
+ upper_z: AIXM::Z.new(alt: 2000, code: :QNH),
18
+ lower_z: AIXM::GROUND
19
+ )
20
+ subject.to_digest.must_equal 'ABF2A04F'
21
+ end
22
+ end
23
+
24
+ describe :to_xml do
25
+ it "must build correct XML with only upper_z and lower_z" do
26
+ subject = AIXM::Vertical::Limits.new(
27
+ upper_z: AIXM::Z.new(alt: 2000, code: :QNH),
28
+ lower_z: AIXM::GROUND
29
+ )
30
+ subject.to_xml.must_equal <<~END
31
+ <codeDistVerUpper>ALT</codeDistVerUpper>
32
+ <valDistVerUpper>2000</valDistVerUpper>
33
+ <uomDistVerUpper>FT</uomDistVerUpper>
34
+ <codeDistVerLower>HEI</codeDistVerLower>
35
+ <valDistVerLower>0</valDistVerLower>
36
+ <uomDistVerLower>FT</uomDistVerLower>
37
+ END
38
+ end
39
+
40
+ it "must build correct XML with additional max_z" do
41
+ subject = AIXM::Vertical::Limits.new(
42
+ upper_z: AIXM::Z.new(alt: 65, code: :QNE),
43
+ lower_z: AIXM::Z.new(alt: 1000, code: :QFE),
44
+ max_z: AIXM::Z.new(alt: 6000, code: :QNH)
45
+ )
46
+ subject.to_xml.must_equal <<~END
47
+ <codeDistVerUpper>STD</codeDistVerUpper>
48
+ <valDistVerUpper>65</valDistVerUpper>
49
+ <uomDistVerUpper>FL</uomDistVerUpper>
50
+ <codeDistVerLower>HEI</codeDistVerLower>
51
+ <valDistVerLower>1000</valDistVerLower>
52
+ <uomDistVerLower>FT</uomDistVerLower>
53
+ <codeDistVerMax>ALT</codeDistVerMax>
54
+ <valDistVerMax>6000</valDistVerMax>
55
+ <uomDistVerMax>FT</uomDistVerMax>
56
+ END
57
+ end
58
+
59
+ it "must build correct XML with additional min_z" do
60
+ subject = AIXM::Vertical::Limits.new(
61
+ upper_z: AIXM::Z.new(alt: 65, code: :QNE),
62
+ lower_z: AIXM::Z.new(alt: 45, code: :QNE),
63
+ min_z: AIXM::Z.new(alt: 3000, code: :QNH)
64
+ )
65
+ subject.to_xml.must_equal <<~END
66
+ <codeDistVerUpper>STD</codeDistVerUpper>
67
+ <valDistVerUpper>65</valDistVerUpper>
68
+ <uomDistVerUpper>FL</uomDistVerUpper>
69
+ <codeDistVerLower>STD</codeDistVerLower>
70
+ <valDistVerLower>45</valDistVerLower>
71
+ <uomDistVerLower>FL</uomDistVerLower>
72
+ <codeDistVerMnm>ALT</codeDistVerMnm>
73
+ <valDistVerMnm>3000</valDistVerMnm>
74
+ <uomDistVerMnm>FT</uomDistVerMnm>
75
+ END
76
+ end
77
+ end
78
+ end