1 #include <marnav/ais/angle.hpp>
13 /// Returns the numeric scale for the specified enumeration.
14 static double scale_value(angle_scale scale
)
27 /// Converts the specified value into an angle (unit: degrees) according
28 /// to the encoded angle in AIS messages. The specified value is a signed value.
30 /// This conversion function is suitable for both, latitudes and longitudes.
32 /// @param[in] value The value from the AIS message to convert.
33 /// @param[in] bits Number of bits of information.
34 /// @param[in] scale Angle scaling.
35 /// @return The converted angle, positive and negative values possible.
36 static double deg_from(uint32_t value
, std::size_t bits
, angle_scale scale
)
41 const uint32_t t
= 1u << (bits
- 1);
43 // treat negative values
44 uint32_t mask
= std::numeric_limits
<uint32_t>::max();
48 return (1.0 / (60.0 * scale_value(scale
))) * static_cast<int32_t>(value
);
51 /// Converts angles in degrees to I4 values, used in AIS messages.
53 /// This conversion function is suitable for both, latitudes and longitudes.
55 /// @param[in] value The angle to convert, may be positive or negative.
56 /// @param[in] bits Number of bits of information in the AIS message.
57 /// @param[in] scale Angle scaling.
58 /// @return The converted angle to be used in AIS messages.
59 static uint32_t deg_to(double value
, std::size_t bits
, angle_scale scale
)
64 uint32_t mask
= std::numeric_limits
<uint32_t>::max();
66 return static_cast<uint32_t>(floor((60.0 * scale_value(scale
)) * value
)) & ~mask
;
69 // used only with static constant values, therefore compile time computation.
70 template <unsigned int n
> double exp_10()
72 return 10.0 * exp_10
<n
- 1>();
74 template <> double exp_10
<0>()
79 template <unsigned int n
> double round_n(double value
)
81 const double factor
= exp_10
<n
>();
82 return std::round(value
* factor
) / factor
;
87 /// Convertes the specified value (commin in AIS data) to latitude.
88 marnav::geo::latitude
to_geo_latitude(
89 uint32_t latitude_minutes
, std::size_t bits
, angle_scale scale
)
91 return geo::latitude
{round_n
<6>(deg_from(latitude_minutes
, bits
, scale
))};
94 /// Converts a latitude to latitude minutes, which is commonly used in AIS data.
95 uint32_t to_latitude_minutes(
96 const marnav::geo::latitude
& lat
, std::size_t bits
, angle_scale scale
)
98 return deg_to(lat
.get(), bits
, scale
);
101 /// Convertes the specified value (commin in AIS data) to longitude.
102 marnav::geo::longitude
to_geo_longitude(
103 uint32_t longitude_minutes
, std::size_t bits
, angle_scale scale
)
105 return geo::longitude
{round_n
<6>(deg_from(longitude_minutes
, bits
, scale
))};
108 /// Converts a longitude to longitude minutes, which is commonly used in AIS data.
109 uint32_t to_longitude_minutes(
110 const marnav::geo::longitude
& lon
, std::size_t bits
, angle_scale scale
)
112 return deg_to(lon
.get(), bits
, scale
);