aixm 0.1.3 → 0.2.0

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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -0
  3. data/README.md +91 -11
  4. data/lib/aixm.rb +10 -0
  5. data/lib/aixm/base.rb +10 -0
  6. data/lib/aixm/component/base.rb +1 -1
  7. data/lib/aixm/component/class_layer.rb +0 -3
  8. data/lib/aixm/component/geometry.rb +0 -3
  9. data/lib/aixm/component/geometry/arc.rb +4 -8
  10. data/lib/aixm/component/geometry/base.rb +8 -0
  11. data/lib/aixm/component/geometry/border.rb +3 -8
  12. data/lib/aixm/component/geometry/circle.rb +5 -9
  13. data/lib/aixm/component/geometry/point.rb +6 -13
  14. data/lib/aixm/component/schedule.rb +8 -10
  15. data/lib/aixm/component/vertical_limits.rb +1 -4
  16. data/lib/aixm/document.rb +9 -6
  17. data/lib/aixm/f.rb +41 -0
  18. data/lib/aixm/feature/airspace.rb +5 -9
  19. data/lib/aixm/feature/base.rb +6 -0
  20. data/lib/aixm/feature/navigational_aid/base.rb +46 -0
  21. data/lib/aixm/feature/navigational_aid/designated_point.rb +69 -0
  22. data/lib/aixm/feature/navigational_aid/dme.rb +54 -0
  23. data/lib/aixm/feature/navigational_aid/marker.rb +41 -0
  24. data/lib/aixm/feature/navigational_aid/ndb.rb +56 -0
  25. data/lib/aixm/feature/navigational_aid/tacan.rb +54 -0
  26. data/lib/aixm/feature/navigational_aid/vor.rb +92 -0
  27. data/lib/aixm/refinements.rb +23 -2
  28. data/lib/aixm/shortcuts.rb +12 -5
  29. data/lib/aixm/version.rb +1 -1
  30. data/lib/aixm/xy.rb +9 -6
  31. data/lib/aixm/z.rb +22 -11
  32. data/spec/factory.rb +87 -4
  33. data/spec/lib/aixm/component/class_layer_spec.rb +6 -6
  34. data/spec/lib/aixm/component/geometry/arc_spec.rb +16 -16
  35. data/spec/lib/aixm/component/geometry/border_spec.rb +4 -4
  36. data/spec/lib/aixm/component/geometry/circle_spec.rb +10 -10
  37. data/spec/lib/aixm/component/geometry/point_spec.rb +4 -4
  38. data/spec/lib/aixm/component/geometry_spec.rb +21 -21
  39. data/spec/lib/aixm/component/schedule_spec.rb +6 -6
  40. data/spec/lib/aixm/component/vertical_limits_spec.rb +18 -18
  41. data/spec/lib/aixm/document_spec.rb +220 -30
  42. data/spec/lib/aixm/f_spec.rb +58 -0
  43. data/spec/lib/aixm/feature/airspace_spec.rb +5 -5
  44. data/spec/lib/aixm/feature/navigational_aid/base_spec.rb +37 -0
  45. data/spec/lib/aixm/feature/navigational_aid/designated_point_spec.rb +43 -0
  46. data/spec/lib/aixm/feature/navigational_aid/dme_spec.rb +43 -0
  47. data/spec/lib/aixm/feature/navigational_aid/marker_spec.rb +44 -0
  48. data/spec/lib/aixm/feature/navigational_aid/ndb_spec.rb +54 -0
  49. data/spec/lib/aixm/feature/navigational_aid/tacan_spec.rb +43 -0
  50. data/spec/lib/aixm/feature/navigational_aid/vor_spec.rb +58 -0
  51. data/spec/lib/aixm/refinements_spec.rb +27 -0
  52. data/spec/lib/aixm/xy_spec.rb +29 -23
  53. data/spec/lib/aixm/z_spec.rb +33 -17
  54. metadata +29 -2
@@ -0,0 +1,92 @@
1
+ module AIXM
2
+ module Feature
3
+ module NavigationalAid
4
+
5
+ ##
6
+ # VOR (VHF omnidirectional range) operate in the frequency band between
7
+ # 108.00 Mhz to 117.95 MHz. Two type of VORs exist:
8
+ #
9
+ # Types:
10
+ # * +:vor+ (+:VOR+) - standard VOR
11
+ # * +:vordme+ (+:DVOR+) - VOR/DME
12
+ #
13
+ # North types:
14
+ # * +:geographic+ (+:TRUE+) - VOR aligned towards geographic north
15
+ # * +:grid+ (+:GRID+) - VOR aligned along north-south lines of the
16
+ # universal transverse mercator grid imposed on
17
+ # topographic maps by the USA and NATO
18
+ # * +:magnetic+ (+:MAG+) - VOR aligned towards magnetic north
19
+ # * +:other+ (+:OTHER+) - other north type
20
+ #
21
+ # https://en.wikipedia.org/wiki/VHF_omnidirectional_range
22
+ class VOR < Base
23
+ using AIXM::Refinements
24
+
25
+ TYPES = {
26
+ VOR: :vor,
27
+ DVOR: :vordme
28
+ }.freeze
29
+
30
+ NORTHS = {
31
+ TRUE: :geographic,
32
+ GRID: :grid,
33
+ MAG: :magnetic,
34
+ OTHER: :other
35
+ }.freeze
36
+
37
+ attr_reader :type, :f, :north
38
+
39
+ public_class_method :new
40
+
41
+ def initialize(id:, name:, xy:, z: nil, type:, f:, north:)
42
+ super(id: id, name: name, xy: xy, z: z)
43
+ @type = TYPES.lookup(type&.to_sym, nil) || fail(ArgumentError, "invalid type")
44
+ @north = NORTHS.lookup(north&.to_sym, nil) || fail(ArgumentError, "invalid north")
45
+ @f = f
46
+ fail(ArgumentError, "invalid frequency") unless f.is_a?(F) && f.between?(108, 117.95, :mhz)
47
+ end
48
+
49
+ ##
50
+ # Digest to identify the payload
51
+ def to_digest
52
+ [super, type, f.to_digest, north].to_digest
53
+ end
54
+
55
+ ##
56
+ # Render AIXM
57
+ def to_xml(*extensions)
58
+ builder = to_builder(*extensions)
59
+ builder.Vor do |vor|
60
+ vor.VorUid({ newEntity: (true if extensions >> :ofm) }.compact) do |voruid|
61
+ voruid.codeId(id)
62
+ voruid.geoLat(xy.lat(format_for(*extensions)))
63
+ voruid.geoLong(xy.long(format_for(*extensions)))
64
+ end
65
+ vor.OrgUid
66
+ vor.txtName(name)
67
+ vor.codeType(type_key.to_s)
68
+ vor.valFreq(f.freq.trim)
69
+ vor.uomFreq(f.unit.upcase.to_s)
70
+ vor.codeTypeNorth(north_key.to_s)
71
+ vor.codeDatum('WGE')
72
+ if z
73
+ vor.valElev(z.alt)
74
+ vor.uomDistVer(z.unit.to_s)
75
+ end
76
+ vor.txtRmk(remarks) if remarks
77
+ vor.target! # see https://github.com/jimweirich/builder/issues/42
78
+ end
79
+ end
80
+
81
+ def type_key
82
+ TYPES.key(type)
83
+ end
84
+
85
+ def north_key
86
+ NORTHS.key(north)
87
+ end
88
+ end
89
+
90
+ end
91
+ end
92
+ end
@@ -25,8 +25,8 @@ module AIXM
25
25
  # Shortcut for +include?+
26
26
  #
27
27
  # Example:
28
- # extensions.include?(:OFM) # => true
29
- # extensions >> :OFM # => true
28
+ # extensions.include?(:ofm) # => true
29
+ # extensions >> :ofm # => true
30
30
  alias_method :>>, :include?
31
31
 
32
32
  ##
@@ -36,6 +36,27 @@ module AIXM
36
36
  end
37
37
  end
38
38
 
39
+ refine Hash do
40
+ ##
41
+ # Fetch a value from the hash, but unlike +fetch+, if +key_or_value+ is
42
+ # no hash key, check whether +key_or_value+ is a hash value and if so
43
+ # return it.
44
+ #
45
+ # Examples:
46
+ # h = { one: 1, two: 2, three: 3, four: :three }
47
+ # h.lookup(:one) # => 1
48
+ # h.lookup(1) # => 1
49
+ # h.lookup(:three) # => 3 (key has priority over value)
50
+ # h.lookup(:foo) # => KeyError
51
+ # h.lookup(:foo, :default) # => :default
52
+ # h.lookup(:foo, nil) # => nil
53
+ def lookup(key_or_value, default = omitted = true)
54
+ self[key_or_value] ||
55
+ (key_or_value if has_value?(key_or_value)) ||
56
+ (omitted ? fail(KeyError, "key or value `#{key_or_value}' not found") : default)
57
+ end
58
+ end
59
+
39
60
  refine String do
40
61
  ##
41
62
  # Indent every line of a string with +number+ spaces
@@ -2,14 +2,11 @@ module AIXM
2
2
 
3
3
  SCHEMA = Pathname(__dir__).join('schemas', '4.5', 'AIXM-Snapshot.xsd').freeze
4
4
 
5
- GROUND = Z.new(alt: 0, code: :QFE).freeze
6
- UNLIMITED = Z.new(alt: 999, code: :QNE).freeze
7
- H24 = Component::Schedule.new(code: :H24).freeze
8
-
9
5
  ELEMENTS = {
10
6
  document: Document,
11
7
  xy: XY,
12
8
  z: Z,
9
+ f: F,
13
10
  airspace: Feature::Airspace,
14
11
  class_layer: Component::ClassLayer,
15
12
  geometry: Component::Geometry,
@@ -18,7 +15,13 @@ module AIXM
18
15
  arc: Component::Geometry::Arc,
19
16
  border: Component::Geometry::Border,
20
17
  circle: Component::Geometry::Circle,
21
- point: Component::Geometry::Point
18
+ point: Component::Geometry::Point,
19
+ dme: Feature::NavigationalAid::DME,
20
+ designated_point: Feature::NavigationalAid::DesignatedPoint,
21
+ marker: Feature::NavigationalAid::Marker,
22
+ tacan: Feature::NavigationalAid::TACAN,
23
+ ndb: Feature::NavigationalAid::NDB,
24
+ vor: Feature::NavigationalAid::VOR
22
25
  }.freeze
23
26
 
24
27
  ELEMENTS.each do |element, klass|
@@ -27,4 +30,8 @@ module AIXM
27
30
  end
28
31
  end
29
32
 
33
+ GROUND = z(0, :qfe).freeze
34
+ UNLIMITED = z(999, :qne).freeze
35
+ H24 = schedule(code: :H24).freeze
36
+
30
37
  end
@@ -1,3 +1,3 @@
1
1
  module AIXM
2
- VERSION = "0.1.3".freeze
2
+ VERSION = "0.2.0".freeze
3
3
  end
@@ -6,8 +6,7 @@ module AIXM
6
6
  # The following notations for longitude and latitude are recognized:
7
7
  # * DD - examples: 12.12345678 (north or east), -12.12345678 (south or west)
8
8
  # * DMS - examples: 11°22'33.44"N, 1112233.44W
9
- class XY
10
-
9
+ class XY < Base
11
10
  using AIXM::Refinements
12
11
 
13
12
  def initialize(lat:, long:)
@@ -18,20 +17,24 @@ module AIXM
18
17
 
19
18
  def lat(format=nil)
20
19
  case format
21
- when :OFM then ("%.8f" % @lat.abs.round(8)) + (@lat.negative? ? 'S' : 'N')
22
- when :AIXM then @lat.to_dms(2).gsub(/[^\d.]/, '') + (@lat.negative? ? 'S' : 'N')
20
+ when :ofm then ("%.8f" % @lat.abs.round(8)) + (@lat.negative? ? 'S' : 'N')
21
+ when :aixm then @lat.to_dms(2).gsub(/[^\d.]/, '') + (@lat.negative? ? 'S' : 'N')
23
22
  else @lat.round(8)
24
23
  end
25
24
  end
26
25
 
27
26
  def long(format=nil)
28
27
  case format
29
- when :OFM then ("%.8f" % @long.abs.round(8)) + (@long.negative? ? 'W' : 'E')
30
- when :AIXM then @long.to_dms(3).gsub(/[^\d.]/, '') + (@long.negative? ? 'W' : 'E')
28
+ when :ofm then ("%.8f" % @long.abs.round(8)) + (@long.negative? ? 'W' : 'E')
29
+ when :aixm then @long.to_dms(3).gsub(/[^\d.]/, '') + (@long.negative? ? 'W' : 'E')
31
30
  else @long.round(8)
32
31
  end
33
32
  end
34
33
 
34
+ def to_digest
35
+ [lat, long].to_digest
36
+ end
37
+
35
38
  def ==(other)
36
39
  other.is_a?(XY) && lat == other.lat && long == other.long
37
40
  end
@@ -4,34 +4,45 @@ module AIXM
4
4
  # Elevation or altitude
5
5
  #
6
6
  # The following Q codes are recognized:
7
- # * QFE - height in feet
8
- # * QNH - altitude in feet
9
- # * QNE - altitude as flight level
10
- class Z
7
+ # * +:qfe+ - height in feet
8
+ # * +:qnh+ - altitude in feet
9
+ # * +:qne+ - altitude as flight level
10
+ class Z < Base
11
+ using AIXM::Refinements
11
12
 
12
- CODES = %i(QFE QNH QNE).freeze
13
+ CODES = %i(qfe qnh qne).freeze
13
14
 
14
15
  attr_reader :alt, :code
15
16
 
16
- def initialize(alt:, code:)
17
- fail(ArgumentError, "unrecognized Q code `#{code}'") unless CODES.include? code
18
- @alt, @code = alt, code
17
+ def initialize(alt, code)
18
+ @alt, @code = alt, code&.to_sym&.downcase
19
+ fail(ArgumentError, "unrecognized Q code `#{code}'") unless CODES.include? @code
20
+ end
21
+
22
+ ##
23
+ # Digest to identify the payload
24
+ def to_digest
25
+ [alt, code].to_digest
19
26
  end
20
27
 
21
28
  def ==(other)
22
29
  other.is_a?(Z) && alt == other.alt && code == other.code
23
30
  end
24
31
 
32
+ CODES.each do |code|
33
+ define_method(:"#{code}?") { @code == code }
34
+ end
35
+
25
36
  def ground?
26
- @code == :QFE && @alt == 0
37
+ qfe? && @alt == 0
27
38
  end
28
39
 
29
40
  def base
30
- @code == :QFE ? :ASFC : :AMSL
41
+ qfe? ? :ASFC : :AMSL
31
42
  end
32
43
 
33
44
  def unit
34
- @code == :QNE ? :FL : :FT
45
+ qne? ? :FL : :FT
35
46
  end
36
47
 
37
48
  end
@@ -2,12 +2,16 @@ module AIXM
2
2
  class Factory
3
3
  class << self
4
4
 
5
+ def xy
6
+ AIXM.xy(lat: 10, long: 20)
7
+ end
8
+
5
9
  def vertical_limits
6
10
  AIXM.vertical_limits(
7
- upper_z: AIXM.z(alt: 65, code: :QNE),
8
- lower_z: AIXM.z(alt: 45, code: :QNE),
9
- max_z: AIXM.z(alt: 6000, code: :QNH),
10
- min_z: AIXM.z(alt: 3000, code: :QFE)
11
+ upper_z: AIXM.z(65, :qne),
12
+ lower_z: AIXM.z(45, :qne),
13
+ max_z: AIXM.z(6000, :qnh),
14
+ min_z: AIXM.z(3000, :qfe)
11
15
  )
12
16
  end
13
17
 
@@ -70,11 +74,90 @@ module AIXM
70
74
  end
71
75
  end
72
76
 
77
+ def designated_point
78
+ AIXM.designated_point(
79
+ id: 'DPN',
80
+ name: 'DESIGNATED POINT NAVAID',
81
+ xy: AIXM.xy(lat: %q(47°51'33"N), long: %q(007°33'36"E)),
82
+ z: AIXM.z(500, :qnh),
83
+ type: :ICAO
84
+ ).tap do |designated_point|
85
+ designated_point.remarks = 'designated point navaid'
86
+ end
87
+ end
88
+
89
+ def dme
90
+ AIXM.dme(
91
+ id: 'DME',
92
+ name: 'DME NAVAID',
93
+ xy: AIXM.xy(lat: %q(47°51'33"N), long: %q(007°33'36"E)),
94
+ z: AIXM.z(500, :qnh),
95
+ channel: '95X'
96
+ ).tap do |dme|
97
+ dme.remarks = 'dme navaid'
98
+ end
99
+ end
100
+
101
+ def marker
102
+ AIXM.marker(
103
+ id: '---',
104
+ name: 'MARKER NAVAID',
105
+ xy: AIXM.xy(lat: %q(47°51'33"N), long: %q(007°33'36"E)),
106
+ z: AIXM.z(500, :qnh)
107
+ ).tap do |marker|
108
+ marker.remarks = 'marker navaid'
109
+ end
110
+ end
111
+
112
+ def ndb
113
+ AIXM.ndb(
114
+ id: 'NDB',
115
+ name: 'NDB NAVAID',
116
+ xy: AIXM.xy(lat: %q(47°51'33"N), long: %q(007°33'36"E)),
117
+ z: AIXM.z(500, :qnh),
118
+ f: AIXM.f(555, :khz)
119
+ ).tap do |ndb|
120
+ ndb.remarks = 'ndb navaid'
121
+ end
122
+ end
123
+
124
+ def tacan
125
+ AIXM.tacan(
126
+ id: 'TCN',
127
+ name: 'TACAN NAVAID',
128
+ xy: AIXM.xy(lat: %q(47°51'33"N), long: %q(007°33'36"E)),
129
+ z: AIXM.z(500, :qnh),
130
+ channel: '29X'
131
+ ).tap do |tacan|
132
+ tacan.remarks = 'tacan navaid'
133
+ end
134
+ end
135
+
136
+ def vor
137
+ AIXM.vor(
138
+ id: 'VOR',
139
+ name: 'VOR NAVAID',
140
+ xy: AIXM.xy(lat: %q(47°51'33"N), long: %q(007°33'36"E)),
141
+ z: AIXM.z(500, :qnh),
142
+ type: :VOR,
143
+ f: AIXM.f(111, :mhz),
144
+ north: :geographic
145
+ ).tap do |vor|
146
+ vor.remarks = 'vor navaid'
147
+ end
148
+ end
149
+
73
150
  def document
74
151
  time = Time.parse('2018-01-18 12:00:00 +0100')
75
152
  AIXM.document(created_at: time, effective_at: time).tap do |document|
76
153
  document.features << AIXM::Factory.polygon_airspace
77
154
  document.features << AIXM::Factory.circle_airspace
155
+ document.features << AIXM::Factory.designated_point
156
+ document.features << AIXM::Factory.dme
157
+ document.features << AIXM::Factory.marker
158
+ document.features << AIXM::Factory.ndb
159
+ document.features << AIXM::Factory.vor
160
+ document.features << AIXM::Factory.tacan
78
161
  end
79
162
  end
80
163
 
@@ -3,19 +3,19 @@ require_relative '../../../spec_helper'
3
3
  describe AIXM::Component::ClassLayer do
4
4
  describe :initialize do
5
5
  it "won't accept invalid arguments" do
6
- -> { AIXM::Component::ClassLayer.new(class: 'X', vertical_limits: AIXM::Factory.vertical_limits ) }.must_raise ArgumentError
7
- -> { AIXM::Component::ClassLayer.new(class: 'A', vertical_limits: 'foobar') }.must_raise ArgumentError
6
+ -> { AIXM.class_layer(class: 'X', vertical_limits: AIXM::Factory.vertical_limits ) }.must_raise ArgumentError
7
+ -> { AIXM.class_layer(class: 'A', vertical_limits: 'foobar') }.must_raise ArgumentError
8
8
  end
9
9
  end
10
10
 
11
11
  context "with class" do
12
12
  subject do
13
- AIXM::Component::ClassLayer.new(class: :C, vertical_limits: AIXM::Factory.vertical_limits)
13
+ AIXM.class_layer(class: :C, vertical_limits: AIXM::Factory.vertical_limits)
14
14
  end
15
15
 
16
16
  describe :to_digest do
17
17
  it "must return digest of payload" do
18
- subject.to_digest.must_equal 612555203
18
+ subject.to_digest.must_equal 385936206
19
19
  end
20
20
  end
21
21
 
@@ -42,12 +42,12 @@ describe AIXM::Component::ClassLayer do
42
42
 
43
43
  context "without class" do
44
44
  subject do
45
- AIXM::Component::ClassLayer.new(vertical_limits: AIXM::Factory.vertical_limits)
45
+ AIXM.class_layer(vertical_limits: AIXM::Factory.vertical_limits)
46
46
  end
47
47
 
48
48
  describe :to_digest do
49
49
  it "must return digest of payload" do
50
- subject.to_digest.must_equal 486148039
50
+ subject.to_digest.must_equal 5930767
51
51
  end
52
52
  end
53
53
 
@@ -3,26 +3,26 @@ require_relative '../../../../spec_helper'
3
3
  describe AIXM::Component::Geometry::Arc do
4
4
  describe :initialize do
5
5
  it "won't accept invalid arguments" do
6
- xy = AIXM::XY.new(lat: 11.1, long: 22.2)
7
- -> { AIXM::Component::Geometry::Arc.new(xy: 0, center_xy: xy, clockwise: true) }.must_raise ArgumentError
8
- -> { AIXM::Component::Geometry::Arc.new(xy: xy, center_xy: 0, clockwise: true) }.must_raise ArgumentError
9
- -> { AIXM::Component::Geometry::Arc.new(xy: xy, center_xy: xy, clockwise: 0) }.must_raise ArgumentError
6
+ xy = AIXM.xy(lat: 11.1, long: 22.2)
7
+ -> { AIXM.arc(xy: 0, center_xy: xy, clockwise: true) }.must_raise ArgumentError
8
+ -> { AIXM.arc(xy: xy, center_xy: 0, clockwise: true) }.must_raise ArgumentError
9
+ -> { AIXM.arc(xy: xy, center_xy: xy, clockwise: 0) }.must_raise ArgumentError
10
10
  end
11
11
  end
12
12
 
13
13
  describe :clockwise? do
14
14
  it "must return true or false" do
15
- xy = AIXM::XY.new(lat: 11.1, long: 22.2)
16
- AIXM::Component::Geometry::Arc.new(xy: xy, center_xy: xy, clockwise: true).must_be :clockwise?
17
- AIXM::Component::Geometry::Arc.new(xy: xy, center_xy: xy, clockwise: false).wont_be :clockwise?
15
+ xy = AIXM.xy(lat: 11.1, long: 22.2)
16
+ AIXM.arc(xy: xy, center_xy: xy, clockwise: true).must_be :clockwise?
17
+ AIXM.arc(xy: xy, center_xy: xy, clockwise: false).wont_be :clockwise?
18
18
  end
19
19
  end
20
20
 
21
21
  describe :to_digest do
22
22
  it "must return digest of payload" do
23
- subject = AIXM::Component::Geometry::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),
23
+ subject = AIXM.arc(
24
+ xy: AIXM.xy(lat: 11.1, long: 33.3),
25
+ center_xy: AIXM.xy(lat: 22.2, long: 33.3),
26
26
  clockwise: true
27
27
  )
28
28
  subject.to_digest.must_equal 712900173
@@ -31,9 +31,9 @@ describe AIXM::Component::Geometry::Arc do
31
31
 
32
32
  describe :to_xml do
33
33
  it "must build correct XML for clockwise arcs" do
34
- subject = AIXM::Component::Geometry::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),
34
+ subject = AIXM.arc(
35
+ xy: AIXM.xy(lat: 11.1, long: 33.3),
36
+ center_xy: AIXM.xy(lat: 22.2, long: 33.3),
37
37
  clockwise: true
38
38
  )
39
39
  subject.to_xml.must_equal <<~END
@@ -49,9 +49,9 @@ describe AIXM::Component::Geometry::Arc do
49
49
  end
50
50
 
51
51
  it "must build correct XML for counter-clockwise arcs" do
52
- subject = AIXM::Component::Geometry::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),
52
+ subject = AIXM.arc(
53
+ xy: AIXM.xy(lat: 11.1, long: 33.3),
54
+ center_xy: AIXM.xy(lat: 22.2, long: 33.3),
55
55
  clockwise: false
56
56
  )
57
57
  subject.to_xml.must_equal <<~END