diff --git a/src/goesproc/map_drawer.cc b/src/goesproc/map_drawer.cc index f5f6a69a..d8f96c0b 100644 --- a/src/goesproc/map_drawer.cc +++ b/src/goesproc/map_drawer.cc @@ -5,12 +5,12 @@ using namespace nlohmann; namespace { Proj longitudeToProj(float longitude) { - std::stringstream args; - args << "+proj=geos "; - args << "+h=35786023.0 "; - args << "+lon_0=" << std::to_string(longitude) << " "; - args << "+sweep=x"; - return Proj(args.str()); + std::map args; + args["proj"] = "geos"; + args["h"] = "35786023.0"; + args["lon_0"] = std::to_string(longitude); + args["sweep"] = "x"; + return Proj(args); } } // namespace diff --git a/src/goesproc/proj.cc b/src/goesproc/proj.cc index 50634c51..bc491101 100644 --- a/src/goesproc/proj.cc +++ b/src/goesproc/proj.cc @@ -5,6 +5,85 @@ namespace { +std::vector toVector(const std::map& args) { + std::vector vargs; + vargs.reserve(args.size()); + for (const auto& arg : args) { + std::stringstream ss; + ss << arg.first << "=" << arg.second; + vargs.push_back(ss.str()); + } + return vargs; +} + +} + +#if PROJ_VERSION_MAJOR == 4 + +namespace { + +std::string pj_error(std::string prefix = "proj: ") { + std::stringstream ss; + ss << prefix << pj_strerrno(pj_errno); + return ss.str(); +} + +} // namespace + +// Forward compatibility. +double proj_torad (double angle_in_degrees) { + return angle_in_degrees * DEG_TO_RAD; +} + +Proj::Proj(const std::vector& args) { + std::vector argv; + for (const auto& arg : args) { + argv.push_back(strdup(arg.c_str())); + } + proj_ = pj_init(argv.size(), argv.data()); + if (!proj_) { + throw std::runtime_error(pj_error("proj initialization error: ")); + } + for (auto& arg : argv) { + free(arg); + } +} + +Proj::Proj(const std::map& args) + : Proj(toVector(args)) { +} + +Proj::~Proj() { + pj_free(proj_); +} + +std::tuple Proj::fwd(double lon, double lat) { + projUV in = { lon, lat }; + projXY out = pj_fwd(in, proj_); + return std::make_tuple(std::move(out.u), std::move(out.v)); +} + +std::tuple Proj::inv(double x, double y) { + projXY in = { x, y }; + projUV out = pj_inv(in, proj_); + return std::make_tuple(std::move(out.u), std::move(out.v)); +} + +#elif PROJ_VERSION_MAJOR >= 5 + +namespace { + +std::string toString(const std::vector& vargs) { + std::stringstream ss; + for (auto it = vargs.begin(); it != vargs.end(); it++) { + ss << "+" << *it; + if (std::next(it) != std::end(vargs)) { + ss << " "; + } + } + return ss.str(); +} + std::string pj_error(std::string prefix = "proj: ") { std::stringstream ss; ss << prefix << proj_errno_string(proj_errno(NULL)); @@ -13,13 +92,18 @@ std::string pj_error(std::string prefix = "proj: ") { } // namespace -Proj::Proj(const std::string& args) { +Proj::Proj(const std::vector& vargs) { + const auto args = toString(vargs); proj_ = proj_create(NULL, args.c_str()); if (!proj_) { throw std::runtime_error(pj_error("proj initialization error: ")); } } +Proj::Proj(const std::map& args) + : Proj(toVector(args)) { +} + Proj::~Proj() { proj_destroy(proj_); } @@ -37,3 +121,5 @@ std::tuple Proj::inv(double x, double y) { PJ_COORD out = proj_trans(proj_, PJ_INV, in); return std::make_tuple(std::move(out.uv.u), std::move(out.uv.v)); } + +#endif diff --git a/src/goesproc/proj.h b/src/goesproc/proj.h index 5c5a86c6..b8cd5edd 100644 --- a/src/goesproc/proj.h +++ b/src/goesproc/proj.h @@ -1,17 +1,28 @@ #pragma once -#if PROJ_VERSION_MAJOR < 5 -#error "proj version >= 5 required" +#if PROJ_VERSION_MAJOR == 4 +#include +#elif PROJ_VERSION_MAJOR >= 5 +#include +#else +#error "proj version >= 4 required" +#endif + +#if PROJ_VERSION_MAJOR == 4 +// Forward compatibility. +double proj_torad (double angle_in_degrees); #endif +#include #include #include - -#include +#include class Proj { public: - explicit Proj(const std::string& args); + explicit Proj(const std::vector& args); + + explicit Proj(const std::map& args); ~Proj(); @@ -20,5 +31,9 @@ class Proj { std::tuple inv(double x, double y); protected: +#if PROJ_VERSION_MAJOR == 4 + projPJ proj_; +#elif PROJ_VERSION_MAJOR >= 5 PJ *proj_; +#endif };