/ proj_hgrid_value() */ / Return coordinate offset in grid */ /
| 3114 | /* Return coordinate offset in grid */ |
| 3115 | /********************************************/ |
| 3116 | PJ_LP pj_hgrid_value(PJ *P, const ListOfHGrids &grids, PJ_LP lp) { |
| 3117 | PJ_LP out = proj_coord_error().lp; |
| 3118 | |
| 3119 | HorizontalShiftGridSet *gridset = nullptr; |
| 3120 | const auto grid = findGrid(grids, lp, gridset); |
| 3121 | if (!grid) { |
| 3122 | proj_context_errno_set(P->ctx, PROJ_ERR_COORD_TRANSFM_OUTSIDE_GRID); |
| 3123 | return out; |
| 3124 | } |
| 3125 | |
| 3126 | /* normalize input to ll origin */ |
| 3127 | const auto &extent = grid->extentAndRes(); |
| 3128 | if (!extent.isGeographic) { |
| 3129 | pj_log(P->ctx, PJ_LOG_ERROR, |
| 3130 | _("Can only handle grids referenced in a geographic CRS")); |
| 3131 | proj_context_errno_set(P->ctx, |
| 3132 | PROJ_ERR_INVALID_OP_FILE_NOT_FOUND_OR_INVALID); |
| 3133 | return out; |
| 3134 | } |
| 3135 | |
| 3136 | const double epsilon = |
| 3137 | (extent.resX + extent.resY) * REL_TOLERANCE_HGRIDSHIFT; |
| 3138 | lp.lam -= extent.west; |
| 3139 | if (lp.lam + epsilon < 0) |
| 3140 | lp.lam += 2 * M_PI; |
| 3141 | else if (lp.lam - epsilon > extent.east - extent.west) |
| 3142 | lp.lam -= 2 * M_PI; |
| 3143 | lp.phi -= extent.south; |
| 3144 | |
| 3145 | out = pj_hgrid_interpolate(lp, grid, false); |
| 3146 | if (grid->hasChanged()) { |
| 3147 | if (gridset->reopen(P->ctx)) { |
| 3148 | return pj_hgrid_value(P, grids, lp); |
| 3149 | } |
| 3150 | out.lam = HUGE_VAL; |
| 3151 | out.phi = HUGE_VAL; |
| 3152 | } |
| 3153 | |
| 3154 | if (out.lam == HUGE_VAL || out.phi == HUGE_VAL) { |
| 3155 | proj_context_errno_set(P->ctx, PROJ_ERR_COORD_TRANSFM_OUTSIDE_GRID); |
| 3156 | } |
| 3157 | |
| 3158 | return out; |
| 3159 | } |
| 3160 | |
| 3161 | // --------------------------------------------------------------------------- |
| 3162 |
no test coverage detected