/
| 264 | |
| 265 | /**************************************************************************************/ |
| 266 | PJ_COORD proj_trans (PJ *P, PJ_DIRECTION direction, PJ_COORD coord) { |
| 267 | /*************************************************************************************** |
| 268 | Apply the transformation P to the coordinate coord, preferring the 4D interfaces if |
| 269 | available. |
| 270 | |
| 271 | See also pj_approx_2D_trans and pj_approx_3D_trans in pj_internal.c, which work |
| 272 | similarly, but prefers the 2D resp. 3D interfaces if available. |
| 273 | ***************************************************************************************/ |
| 274 | if (nullptr==P || direction == PJ_IDENT) |
| 275 | return coord; |
| 276 | if (P->inverted) |
| 277 | direction = opposite_direction(direction); |
| 278 | |
| 279 | if( !P->alternativeCoordinateOperations.empty() ) { |
| 280 | constexpr int N_MAX_RETRY = 2; |
| 281 | int iExcluded[N_MAX_RETRY] = {-1, -1}; |
| 282 | |
| 283 | const int nOperations = static_cast<int>( |
| 284 | P->alternativeCoordinateOperations.size()); |
| 285 | |
| 286 | // We may need several attempts. For example the point at |
| 287 | // lon=-111.5 lat=45.26 falls into the bounding box of the Canadian |
| 288 | // ntv2_0.gsb grid, except that it is not in any of the subgrids, being |
| 289 | // in the US. We thus need another retry that will select the conus |
| 290 | // grid. |
| 291 | for( int iRetry = 0; iRetry <= N_MAX_RETRY; iRetry++ ) |
| 292 | { |
| 293 | // Do a first pass and select the operations that match the area of use |
| 294 | // and has the best accuracy. |
| 295 | int iBest = pj_get_suggested_operation(P->ctx, |
| 296 | P->alternativeCoordinateOperations, |
| 297 | iExcluded, |
| 298 | direction, |
| 299 | coord); |
| 300 | if( iBest < 0 ) { |
| 301 | break; |
| 302 | } |
| 303 | if( iRetry > 0 ) { |
| 304 | const int oldErrno = proj_errno_reset(P); |
| 305 | if (proj_log_level(P->ctx, PJ_LOG_TELL) >= PJ_LOG_DEBUG) { |
| 306 | pj_log(P->ctx, PJ_LOG_DEBUG, proj_context_errno_string(P->ctx, oldErrno)); |
| 307 | } |
| 308 | pj_log(P->ctx, PJ_LOG_DEBUG, |
| 309 | "Did not result in valid result. " |
| 310 | "Attempting a retry with another operation."); |
| 311 | } |
| 312 | |
| 313 | const auto& alt = P->alternativeCoordinateOperations[iBest]; |
| 314 | if( P->iCurCoordOp != iBest ) { |
| 315 | if (proj_log_level(P->ctx, PJ_LOG_TELL) >= PJ_LOG_DEBUG) { |
| 316 | std::string msg("Using coordinate operation "); |
| 317 | msg += alt.name; |
| 318 | pj_log(P->ctx, PJ_LOG_DEBUG, msg.c_str()); |
| 319 | } |
| 320 | P->iCurCoordOp = iBest; |
| 321 | } |
| 322 | PJ_COORD res = direction == PJ_FWD ? |
| 323 | pj_fwd4d( coord, alt.pj ) : pj_inv4d( coord, alt.pj ); |
no test coverage detected