Loading...
Searching...
No Matches
projection_factories.cuh
Go to the documentation of this file.
1/*
2 * Copyright (c) 2023, NVIDIA CORPORATION.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#pragma once
18
19#include <cuproj/error.hpp>
20#include <cuproj/projection.cuh>
22
23#include <memory>
24
25namespace cuproj {
26
32namespace detail {
33
38class epsg_code {
39 public:
41 explicit epsg_code(std::string const& str) : str_(str)
42 {
43 std::transform(str_.begin(), str_.end(), str_.begin(), ::toupper);
44 CUPROJ_EXPECTS(valid_prefix(), "EPSG code must start with 'EPSG:'");
45
46 try {
47 epsg_ = std::stoi(str_.substr(str_.find_first_not_of("EPSG:")));
48 } catch (std::invalid_argument const&) {
49 CUPROJ_FAIL("Invalid EPSG code");
50 }
51 }
52
54 explicit epsg_code(int code) : str_("EPSG:" + std::to_string(code)), epsg_(code) {}
55
56 explicit operator std::string() const { return str_; } //< Return the EPSG code as a string
57 explicit operator int() const { return epsg_; } //< Return the EPSG code as an integer
58
59 // Return true if the EPSG code is for WGS84 (4326), false otherwise
60 inline bool is_wgs_84() const { return epsg_ == 4326; }
61
63 inline auto to_utm_zone()
64 {
65 if (epsg_ >= 32601 && epsg_ <= 32660) {
66 return std::make_pair(epsg_ - 32600, hemisphere::NORTH);
67 } else if (epsg_ >= 32701 && epsg_ <= 32760) {
68 return std::make_pair(epsg_ - 32700, hemisphere::SOUTH);
69 } else {
70 CUPROJ_FAIL("Unsupported UTM EPSG code. Must be in range [32601, 32760] or [32701, 32760]]");
71 }
72 }
73
74 private:
75 std::string str_;
76 int epsg_;
77
79 inline bool valid_prefix() const { return str_.find("EPSG:") == 0; }
80};
81
82} // namespace detail
83
95template <typename Coordinate, typename T = typename Coordinate::value_type>
98 direction dir = direction::FORWARD)
99{
100 projection_parameters<T> tmerc_proj_params{
101 make_ellipsoid_wgs84<T>(), zone, hemisphere, T{0}, T{0}};
102
103 std::vector<cuproj::operation_type> h_utm_pipeline{
104 operation_type::AXIS_SWAP,
105 operation_type::DEGREES_TO_RADIANS,
106 operation_type::CLAMP_ANGULAR_COORDINATES,
107 operation_type::TRANSVERSE_MERCATOR,
108 operation_type::OFFSET_SCALE_CARTESIAN_COORDINATES};
109
110 return new projection<Coordinate>(h_utm_pipeline, tmerc_proj_params, dir);
111}
112
127template <typename Coordinate>
129 detail::epsg_code const& dst_epsg)
130{
131 detail::epsg_code src_code{src_epsg};
132 detail::epsg_code dst_code{dst_epsg};
133
134 auto dir = [&]() {
135 if (src_code.is_wgs_84()) {
136 return direction::FORWARD;
137 } else {
138 std::swap(src_code, dst_code);
139 CUPROJ_EXPECTS(src_code.is_wgs_84(), "Unsupported CRS combination.");
140 return direction::INVERSE;
141 }
142 }();
143
144 auto [dst_zone, dst_hemisphere] = dst_code.to_utm_zone();
145 return make_utm_projection<Coordinate>(dst_zone, dst_hemisphere, dir);
146}
147
164template <typename Coordinate>
166 std::string const& dst_epsg)
167{
168 detail::epsg_code src_code{src_epsg};
169 detail::epsg_code dst_code{dst_epsg};
170
171 return make_projection<Coordinate>(src_code, dst_code);
172}
173
188template <typename Coordinate>
189cuproj::projection<Coordinate>* make_projection(int src_epsg, int const& dst_epsg)
190{
191 detail::epsg_code src_code{src_epsg};
192 detail::epsg_code dst_code{dst_epsg};
193
195}
196
201} // namespace cuproj
auto to_utm_zone()
Return a [zone, hemisphere] pair for the UTM zone corresponding to the EPSG code.
epsg_code(std::string const &str)
Construct an epsg_code from a string.
epsg_code(int code)
Construct an epsg_code from an integer.
A projection transforms coordinates between coordinate reference systems.
#define CUPROJ_EXPECTS(cond, reason)
Macro for checking (pre-)conditions that throws an exception when a condition is violated.
Definition error.hpp:76
#define CUPROJ_FAIL(reason)
Indicates that an erroneous code path has been taken.
Definition error.hpp:118
constexpr ellipsoid< T > make_ellipsoid_wgs84()
Create the WGS84 ellipsoid.
Definition ellipsoid.hpp:71
direction
Enumerates the direction of a transform operation.
Definition operation.cuh:44
projection< Coordinate > * make_utm_projection(int zone, hemisphere hemisphere, direction dir=direction::FORWARD)
Create a WGS84<-->UTM projection for the given UTM zone and hemisphere.
cuproj::projection< Coordinate > * make_projection(detail::epsg_code const &src_epsg, detail::epsg_code const &dst_epsg)
Create a projection object from EPSG codes.
hemisphere
Hemisphere identifier for projections.