lib/aixm/feature/navigational_aid/vor.rb in aixm-0.2.3 vs lib/aixm/feature/navigational_aid/vor.rb in aixm-0.3.0

- old
+ new

@@ -1,130 +1,138 @@ +using AIXM::Refinements + module AIXM - module Feature - module NavigationalAid + class Feature + class NavigationalAid - ## - # VOR (VHF omnidirectional range) operate in the frequency band between - # 108.00 Mhz to 117.95 MHz. Two type of VORs exist: + # VHF omni directional radio range (VOR) is a type of radio navigation for + # aircraft to determine their position and course. They operate in the + # frequency band between 108.00 Mhz to 117.95 MHz. # - # Types: - # * +:vor+ (+:VOR+) - conventional VOR (also known as CVOR) - # * +:doppler_vor+ (+:DVOR+) - Doppler VOR + # ===Cheat Sheet in Pseudo Code: + # vor = AIXM.vor( + # source: String or nil + # region: String or nil (falls back to AIXM.config.region) + # organisation: AIXM.organisation + # id: String + # name: String + # xy: AIXM.xy + # z: AIXM.z or nil + # type: TYPES + # f: AIXM.f + # north: NORTHS + # ) + # vor.timetable = AIXM.timetable or nil + # vor.remarks = String or nil + # vor.associate_dme(channel: String) # turns the VOR into a VOR/DME + # vor.associate_tacan(channel: String) # turns the VOR into a VORTAC # - # North types: - # * +:geographic+ (+:TRUE+) - VOR aligned towards geographic north - # * +:grid+ (+:GRID+) - VOR aligned along north-south lines of the - # universal transverse mercator grid imposed on - # topographic maps by the USA and NATO - # * +:magnetic+ (+:MAG+) - VOR aligned towards magnetic north - # - # https://en.wikipedia.org/wiki/VHF_omnidirectional_range - class VOR < Base - using AIXM::Refinements + # @see https://github.com/openflightmaps/ofmx/wiki/Navigational-aid#vor-vor + class VOR < NavigationalAid + public_class_method :new TYPES = { VOR: :conventional, - DVOR: :doppler + DVOR: :doppler, + OTHER: :other # specify in remarks }.freeze NORTHS = { TRUE: :geographic, - GRID: :grid, - MAG: :magnetic + GRID: :grid, # parallel to the north-south lines of the UTM grid + MAG: :magnetic, + OTHER: :other # specify in remarks }.freeze - attr_reader :type, :f, :north, :dme, :tacan + # @return [Symbol] type of VOR (see {TYPES}) + attr_reader :type - public_class_method :new + # @return [AIXM::F] radio requency + attr_reader :f - def initialize(id:, name:, xy:, z: nil, type:, f:, north:) - super(id: id, name: name, xy: xy, z: z) + # @return [Symbol] north indication (see {NORTHS}) + attr_reader :north + + # @return [AIXM::Feature::NavigationalAid::DME, nil] associated DME + attr_reader :dme + + # @return [AIXM::Feature::NavigationalAid::TACAN, nil] associated TACAN + attr_reader :tacan + + def initialize(type:, f:, north:, **arguments) + super(**arguments) self.type, self.f, self.north = type, f, north end def type=(value) - @type = TYPES.lookup(value&.to_sym, nil) || fail(ArgumentError, "invalid type") + @type = TYPES.lookup(value&.to_s&.to_sym, nil) || fail(ArgumentError, "invalid type") end - def type_key - TYPES.key(type) - end - def f=(value) fail(ArgumentError, "invalid f") unless value.is_a?(F) && value.between?(108, 117.95, :mhz) @f = value end def north=(value) - @north = NORTHS.lookup(value&.to_sym, nil) || fail(ArgumentError, "invalid north") + @north = NORTHS.lookup(value&.to_s&.to_sym, nil) || fail(ArgumentError, "invalid north") end - def north_key - NORTHS.key(north) - end - - ## - # Associate a DME (also known as VOR/DME) + # Associate a DME which turns the VOR into a VOR/DME def associate_dme(channel:) - @dme = AIXM.dme(id: id, name: name, xy: xy, z: z, channel: channel) - @dme.schedule = schedule - @dme.remarks = remarks - @dme.vor = self + @dme = AIXM.dme(organisation: organisation, id: id, name: name, xy: xy, z: z, channel: channel) + @dme.region, @dme.timetable, @dme.remarks = region, timetable, remarks + @dme.send(:vor=, self) end - ## - # Associate a TACAN (also known as VORTAC) + # Associate a TACAN which turns the VOR into a VORTAC def associate_tacan(channel:) - @tacan = AIXM.tacan(id: id, name: name, xy: xy, z: z, channel: channel) - @tacan.schedule = schedule - @tacan.remarks = remarks - @tacan.vor = self + @tacan = AIXM.tacan(organisation: organisation, id: id, name: name, xy: xy, z: z, channel: channel) + @tacan.region, @tacan.timetable, @tacan.remarks = region, timetable, remarks + @tacan.send(:vor=, self) end - ## - # Digest to identify the payload - def to_digest - [super, type, f.to_digest, north].to_digest - end - - ## - # Render UID markup - def to_uid(*extensions) + # @return [String] UID markup + def to_uid builder = Builder::XmlMarkup.new(indent: 2) - builder.VorUid({ mid: to_digest, newEntity: (true if extensions >> :ofm) }.compact) do |voruid| - voruid.codeId(id) - voruid.geoLat(xy.lat(format_for(*extensions))) - voruid.geoLong(xy.long(format_for(*extensions))) + builder.VorUid({ region: (region if AIXM.ofmx?) }.compact) do |vor_uid| + vor_uid.codeId(id) + vor_uid.geoLat(xy.lat(AIXM.schema)) + vor_uid.geoLong(xy.long(AIXM.schema)) end end - ## - # Render AIXM markup - def to_aixm(*extensions) - builder = to_builder(*extensions) - builder.Vor do |vor| - vor << to_uid(*extensions).indent(2) - vor.OrgUid + # @return [String] AIXM or OFMX markup + def to_xml + builder = to_builder + builder.Vor({ source: (source if AIXM.ofmx?) }.compact) do |vor| + vor << to_uid.indent(2) + vor << organisation.to_uid.indent(2) vor.txtName(name) if name vor.codeType(type_key.to_s) vor.valFreq(f.freq.trim) vor.uomFreq(f.unit.upcase.to_s) vor.codeTypeNorth(north_key.to_s) vor.codeDatum('WGE') if z vor.valElev(z.alt) - vor.uomDistVer(z.unit.to_s) + vor.uomDistVer(z.unit.upcase.to_s) end - if schedule - vor.Vtt do |vtt| - vtt << schedule.to_aixm(*extensions).indent(4) - end - end + vor << timetable.to_xml(as: :Vtt).indent(2) if timetable vor.txtRmk(remarks) if remarks end - builder << @dme.to_aixm(*extensions) if @dme - builder << @tacan.to_aixm(*extensions) if @tacan - builder.target! # see https://github.com/jimweirich/builder/issues/42 + builder << @dme.to_xml if @dme + builder << @tacan.to_xml if @tacan + builder.target! + end + + # @api private + def type_key + TYPES.key(type) + end + + # @api private + def north_key + NORTHS.key(north) end end end end