18#include <gsl/pointers>
31 static constexpr std::size_t zone_width{6};
32 static constexpr std::size_t max_zones{60};
36 static_cast<std::size_t
>(
44 zone.
number = std::min(number, max_zones);
46 if (coordinate.latitude < units::angle::degree_t{0.0}) {
58 gsl::owner<PJ_CONTEXT *> context = proj_context_create();
59 proj_log_level(context, PJ_LOG_NONE);
62 const std::string error_string{proj_errno_string(proj_context_errno(context))};
63 throw std::invalid_argument(
"Could not create PROJ context: " + error_string +
'.');
66 gsl ::owner<PJ *> transformation =
67 proj_create_crs_to_crs(context,
"EPSG:4326", proj_string.data(),
nullptr);
69 if (!transformation) {
70 const std::string error_string{proj_errno_string(proj_context_errno(context))};
71 throw std::invalid_argument(
"Could not create PROJ transform: " + error_string +
'.');
74 const auto coord_wgs84 = proj_coord(
77 const auto coord_projected = proj_trans(transformation, PJ_FWD, coord_wgs84);
79 proj_destroy(transformation);
80 proj_context_destroy(context);
83 units::length::meter_t{coord_projected.enu.e}, units::length::meter_t{coord_projected.enu.n},
84 units::length::meter_t{coordinate.elevation}};
89 gsl::owner<PJ_CONTEXT *> context = proj_context_create();
90 proj_log_level(context, PJ_LOG_NONE);
92 if (context ==
nullptr) {
93 const std::string error_string{proj_errno_string(proj_context_errno(context))};
94 throw std::invalid_argument(
"Could not create PROJ context: " + error_string +
'.');
98 std::string proj_string{
"+proj=utm +zone=" +
std::to_string(utm_zone.number) +
" +datum=WGS84"};
101 proj_string +=
" +south";
104 gsl ::owner<PJ *> utm_transformation =
105 proj_create_crs_to_crs(context,
"EPSG:4326", proj_string.c_str(),
nullptr);
107 if (utm_transformation ==
nullptr) {
108 const std::string error_string{proj_errno_string(proj_context_errno(context))};
109 throw std::invalid_argument(
"Could not create PROJ transform: " + error_string +
'.');
112 auto coord_wgs84 = proj_coord(
115 auto coord_utm = proj_trans(utm_transformation, PJ_FWD, coord_wgs84);
117 proj_destroy(utm_transformation);
118 proj_context_destroy(context);
121 utm_zone, units::length::meter_t{coord_utm.enu.e}, units::length::meter_t{coord_utm.enu.n},
122 units::length::meter_t{coordinate.elevation}};
126 -> units::angle::degree_t
128 gsl::owner<PJ_CONTEXT *> context = proj_context_create();
129 proj_log_level(context, PJ_LOG_NONE);
131 if (context ==
nullptr) {
132 const std::string error_string{proj_errno_string(proj_context_errno(context))};
133 throw std::invalid_argument(
"Could not create PROJ context: " + error_string +
'.');
136 gsl::owner<PJ *> transform = proj_create(context, georeference.data());
138 const auto factors = proj_factors(
139 transform, proj_coord(
143 if (proj_context_errno(context) != 0) {
144 const std::string error_string{proj_errno_string(proj_context_errno(context))};
145 throw std::invalid_argument(
"Could not calculate PROJ factors: " + error_string +
'.');
148 proj_destroy(transform);
149 proj_context_destroy(context);
151 return units::angle::degree_t{proj_todeg(factors.meridian_convergence)};
155 -> units::angle::degree_t
160 std::string proj_string{
161 "+proj=utm +zone=" +
std::to_string(zone.number) +
" +datum=WGS84 +units=m +no_defs"};
164 proj_string +=
" +south";
auto calculate_grid_convergence(const Wgs84Coordinate &position, const UtmZone &zone) -> units::angle::degree_t
Calculate grid convergence at a given position.
auto project_to_carma_map(const Wgs84Coordinate &coordinate, std::string_view proj_string) -> MapCoordinate
auto to_string(const UtmZone &zone) -> std::string
auto calculate_utm_zone(const Wgs84Coordinate &coordinate) -> UtmZone
Get the UTM zone number from a WGS-84 coordinate.
constexpr auto remove_units(const T &value)
auto project_to_utm(const Wgs84Coordinate &coordinate) -> UtmCoordinate
Projects a Wgs84Coordinate to its corresponding UTM zone.
Represents a position using UTM coordinates.
Represents a position using WGS-84 coordinates.