/ proj_hgrid_value() */ / Return coordinate offset in grid */ /
| 3543 | /* Return coordinate offset in grid */ |
| 3544 | /********************************************/ |
| 3545 | PJ_LP pj_hgrid_value(PJ *P, const ListOfHGrids &grids, PJ_LP lp) { |
| 3546 | PJ_LP out = proj_coord_error().lp; |
| 3547 | |
| 3548 | HorizontalShiftGridSet *gridset = nullptr; |
| 3549 | const auto grid = findGrid(grids, lp, gridset); |
| 3550 | if (!grid) { |
| 3551 | proj_context_errno_set(P->ctx, PROJ_ERR_COORD_TRANSFM_OUTSIDE_GRID); |
| 3552 | return out; |
| 3553 | } |
| 3554 | |
| 3555 | /* normalize input to ll origin */ |
| 3556 | const auto &extent = grid->extentAndRes(); |
| 3557 | if (!extent.isGeographic) { |
| 3558 | pj_log(P->ctx, PJ_LOG_ERROR, |
| 3559 | _("Can only handle grids referenced in a geographic CRS")); |
| 3560 | proj_context_errno_set(P->ctx, |
| 3561 | PROJ_ERR_INVALID_OP_FILE_NOT_FOUND_OR_INVALID); |
| 3562 | return out; |
| 3563 | } |
| 3564 | |
| 3565 | const double epsilon = |
| 3566 | (extent.resX + extent.resY) * REL_TOLERANCE_HGRIDSHIFT; |
| 3567 | lp.lam -= extent.west; |
| 3568 | if (lp.lam + epsilon < 0) |
| 3569 | lp.lam += 2 * M_PI; |
| 3570 | else if (lp.lam - epsilon > extent.east - extent.west) |
| 3571 | lp.lam -= 2 * M_PI; |
| 3572 | lp.phi -= extent.south; |
| 3573 | |
| 3574 | out = pj_hgrid_interpolate(lp, grid, false); |
| 3575 | if (grid->hasChanged()) { |
| 3576 | if (gridset->reopen(P->ctx)) { |
| 3577 | return pj_hgrid_value(P, grids, lp); |
| 3578 | } |
| 3579 | out.lam = HUGE_VAL; |
| 3580 | out.phi = HUGE_VAL; |
| 3581 | } |
| 3582 | |
| 3583 | if (out.lam == HUGE_VAL || out.phi == HUGE_VAL) { |
| 3584 | proj_context_errno_set(P->ctx, PROJ_ERR_COORD_TRANSFM_OUTSIDE_GRID); |
| 3585 | } |
| 3586 | |
| 3587 | return out; |
| 3588 | } |
| 3589 | |
| 3590 | // --------------------------------------------------------------------------- |
| 3591 |
no test coverage detected