Build: add GCC-13, Clang-14, Clang-15, Clang-16, Clang-17
[marnav.git] / src / marnav / nmea / bwc.cpp
blobef57ee867753cfb8d46a24fbd9b1df6050766567
1 #include <marnav/nmea/bwc.hpp>
2 #include "convert.hpp"
3 #include "checks.hpp"
4 #include <marnav/nmea/io.hpp>
6 namespace marnav::nmea
8 constexpr sentence_id bwc::ID;
9 constexpr const char * bwc::TAG;
11 bwc::bwc()
12 : sentence(ID, TAG, talker::global_positioning_system)
16 bwc::bwc(talker talk, fields::const_iterator first, fields::const_iterator last)
17 : sentence(ID, TAG, talk)
19 const auto size = std::distance(first, last);
20 if ((size != 12) && (size != 13))
21 throw std::invalid_argument{"invalid number of fields in bwc"};
23 std::optional<unit::distance> distance_unit;
25 read(*(first + 0), time_utc_);
26 read(*(first + 1), lat_);
27 read(*(first + 2), lat_hem_);
28 read(*(first + 3), lon_);
29 read(*(first + 4), lon_hem_);
30 read(*(first + 5), bearing_true_);
31 read(*(first + 6), bearing_true_ref_);
32 read(*(first + 7), bearing_mag_);
33 read(*(first + 8), bearing_mag_ref_);
34 read(*(first + 9), distance_);
35 read(*(first + 10), distance_unit);
36 read(*(first + 11), waypoint_id_);
38 if (size == 13)
39 read(*(first + 12), mode_ind_);
41 // instead of reading data into temporary lat/lon, let's correct values afterwards
42 lat_ = correct_hemisphere(lat_, lat_hem_);
43 lon_ = correct_hemisphere(lon_, lon_hem_);
45 check_value(distance_unit, {unit::distance::nm}, "distance nautical miles unit");
48 std::optional<geo::longitude> bwc::get_lon() const
50 return (lon_ && lon_hem_) ? lon_ : std::optional<geo::longitude>{};
53 std::optional<geo::latitude> bwc::get_lat() const
55 return (lat_ && lat_hem_) ? lat_ : std::optional<geo::latitude>{};
58 void bwc::set_lat(const geo::latitude & t)
60 lat_ = t;
61 lat_hem_ = convert_hemisphere(t);
64 void bwc::set_lon(const geo::longitude & t)
66 lon_ = t;
67 lon_hem_ = convert_hemisphere(t);
70 void bwc::set_bearing_true(double t) noexcept
72 bearing_true_ = t;
73 bearing_true_ref_ = reference::TRUE;
76 void bwc::set_bearing_mag(double t) noexcept
78 bearing_mag_ = t;
79 bearing_mag_ref_ = reference::MAGNETIC;
82 std::optional<units::length> bwc::get_distance() const
84 if (!distance_)
85 return {};
86 return {*distance_};
89 void bwc::set_distance(units::length t)
91 if (t.value() < 0.0)
92 throw std::invalid_argument{"invalid argument, distance less than zero"};
93 distance_ = t.get<units::nautical_miles>();
96 void bwc::append_data_to(std::string & s, const version &) const
98 append(s, to_string(time_utc_));
99 append(s, to_string(lat_));
100 append(s, to_string(lat_hem_));
101 append(s, to_string(lon_));
102 append(s, to_string(lon_hem_));
103 append(s, to_string(bearing_true_));
104 append(s, to_string(bearing_true_ref_));
105 append(s, to_string(bearing_mag_));
106 append(s, to_string(bearing_mag_ref_));
107 append(s, to_string(distance_));
108 append(s, to_string_if(unit::distance::nm, distance_));
109 append(s, to_string(waypoint_id_));
110 append(s, to_string(mode_ind_));