EVOLUTION-MANAGER
Edit File: gridcatalog.cpp
/****************************************************************************** * Project: PROJ.4 * Purpose: Code in support of grid catalogs * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2012, Frank Warmerdam <warmerdam@pobox.com> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #define PJ_LIB__ #include <assert.h> #include <math.h> #include <stdlib.h> #include <string.h> #include "proj.h" #include "proj_internal.h" static PJ_GridCatalog *grid_catalog_list = nullptr; static PJ_GRIDINFO *pj_gc_findgrid( projCtx_t *ctx, PJ_GridCatalog *catalog, int after, PJ_LP location, double date, PJ_Region *optional_region, double *grid_date ); /************************************************************************/ /* pj_gc_unloadall() */ /* */ /* Deallocate all the grid catalogs (but not the referenced */ /* grids). */ /************************************************************************/ void pj_gc_unloadall( projCtx ctx ) { (void) ctx; while( grid_catalog_list != nullptr ) { int i; PJ_GridCatalog *catalog = grid_catalog_list; grid_catalog_list = grid_catalog_list->next; for( i = 0; i < catalog->entry_count; i++ ) { /* we don't own gridinfo - do not free here */ free( catalog->entries[i].definition ); } free( catalog->entries ); free( catalog->catalog_name ); free( catalog ); } } /************************************************************************/ /* pj_gc_findcatalog() */ /************************************************************************/ PJ_GridCatalog *pj_gc_findcatalog( projCtx ctx, const char *name ) { PJ_GridCatalog *catalog; pj_acquire_lock(); for( catalog=grid_catalog_list; catalog != nullptr; catalog = catalog->next ) { if( strcmp(catalog->catalog_name, name) == 0 ) { pj_release_lock(); return catalog; } } pj_release_lock(); catalog = pj_gc_readcatalog( ctx, name ); if( catalog == nullptr ) return nullptr; pj_acquire_lock(); catalog->next = grid_catalog_list; grid_catalog_list = catalog; pj_release_lock(); return catalog; } /************************************************************************/ /* pj_gc_apply_gridshift() */ /************************************************************************/ int pj_gc_apply_gridshift( PJ *defn, int inverse, long point_count, int point_offset, double *x, double *y, double *z ) { int i; (void) z; if( defn->catalog == nullptr ) { defn->catalog = pj_gc_findcatalog( defn->ctx, defn->catalog_name ); if( defn->catalog == nullptr ) return defn->ctx->last_errno; } defn->ctx->last_errno = 0; for( i = 0; i < point_count; i++ ) { long io = i * point_offset; PJ_LP input, output_after, output_before; double mix_ratio; PJ_GRIDINFO *gi; input.phi = y[io]; input.lam = x[io]; /* make sure we have appropriate "after" shift file available */ if( defn->last_after_grid == nullptr || input.lam < defn->last_after_region.ll_long || input.lam > defn->last_after_region.ur_long || input.phi < defn->last_after_region.ll_lat || input.phi > defn->last_after_region.ll_lat ) { defn->last_after_grid = pj_gc_findgrid( defn->ctx, defn->catalog, 1, input, defn->datum_date, &(defn->last_after_region), &(defn->last_after_date)); if( defn->last_after_grid == nullptr ) { pj_ctx_set_errno( defn->ctx, PJD_ERR_FAILED_TO_LOAD_GRID ); return PJD_ERR_FAILED_TO_LOAD_GRID; } } gi = defn->last_after_grid; assert( gi->child == nullptr ); /* load the grid shift info if we don't have it. */ if( gi->ct->cvs == nullptr && !pj_gridinfo_load( defn->ctx, gi ) ) { pj_ctx_set_errno( defn->ctx, PJD_ERR_FAILED_TO_LOAD_GRID ); return PJD_ERR_FAILED_TO_LOAD_GRID; } output_after = nad_cvt( defn->ctx, input, inverse, gi->ct, 0, nullptr ); if( output_after.lam == HUGE_VAL ) { if( defn->ctx->debug_level >= PJ_LOG_DEBUG_MAJOR ) { pj_log( defn->ctx, PJ_LOG_DEBUG_MAJOR, "pj_apply_gridshift(): failed to find a grid shift table for\n" " location (%.7fdW,%.7fdN)", x[io] * RAD_TO_DEG, y[io] * RAD_TO_DEG ); } continue; } if( defn->datum_date == 0.0 ) { y[io] = output_after.phi; x[io] = output_after.lam; continue; } /* make sure we have appropriate "before" shift file available */ if( defn->last_before_grid == nullptr || input.lam < defn->last_before_region.ll_long || input.lam > defn->last_before_region.ur_long || input.phi < defn->last_before_region.ll_lat || input.phi > defn->last_before_region.ll_lat ) { defn->last_before_grid = pj_gc_findgrid( defn->ctx, defn->catalog, 0, input, defn->datum_date, &(defn->last_before_region), &(defn->last_before_date)); if( defn->last_before_grid == nullptr ) { pj_ctx_set_errno( defn->ctx, PJD_ERR_FAILED_TO_LOAD_GRID ); return PJD_ERR_FAILED_TO_LOAD_GRID; } } gi = defn->last_before_grid; assert( gi->child == nullptr ); /* load the grid shift info if we don't have it. */ if( gi->ct->cvs == nullptr && !pj_gridinfo_load( defn->ctx, gi ) ) { pj_ctx_set_errno( defn->ctx, PJD_ERR_FAILED_TO_LOAD_GRID ); return PJD_ERR_FAILED_TO_LOAD_GRID; } output_before = nad_cvt( defn->ctx, input, inverse, gi->ct, 0, nullptr ); if( output_before.lam == HUGE_VAL ) { if( defn->ctx->debug_level >= PJ_LOG_DEBUG_MAJOR ) { pj_log( defn->ctx, PJ_LOG_DEBUG_MAJOR, "pj_apply_gridshift(): failed to find a grid shift table for\n" " location (%.7fdW,%.7fdN)", x[io] * RAD_TO_DEG, y[io] * RAD_TO_DEG ); } continue; } mix_ratio = (defn->datum_date - defn->last_before_date) / (defn->last_after_date - defn->last_before_date); y[io] = mix_ratio * output_after.phi + (1.0-mix_ratio) * output_before.phi; x[io] = mix_ratio * output_after.lam + (1.0-mix_ratio) * output_before.lam; } return 0; } /************************************************************************/ /* pj_c_findgrid() */ /************************************************************************/ static PJ_GRIDINFO *pj_gc_findgrid( projCtx ctx, PJ_GridCatalog *catalog, int after, PJ_LP location, double date, PJ_Region *optional_region, double *grid_date ) { int iEntry; PJ_GridCatalogEntry *entry = nullptr; for( iEntry = 0; iEntry < catalog->entry_count; iEntry++ ) { entry = catalog->entries + iEntry; if( (after && entry->date < date) || (!after && entry->date > date) ) continue; if( location.lam < entry->region.ll_long || location.lam > entry->region.ur_long || location.phi < entry->region.ll_lat || location.phi > entry->region.ur_lat ) continue; if( entry->available == -1 ) continue; break; } if( entry == nullptr ) { if( grid_date ) *grid_date = 0.0; if( optional_region != nullptr ) memset( optional_region, 0, sizeof(PJ_Region)); return nullptr; } if( grid_date ) *grid_date = entry->date; if( optional_region ) { } if( entry->gridinfo == nullptr ) { PJ_GRIDINFO **gridlist = nullptr; int grid_count = 0; gridlist = pj_gridlist_from_nadgrids( ctx, entry->definition, &grid_count); // FIXME: this leaks gridlist itself, and memory ownership of // entry->gridinfo is also confusing. Coverity CID 193539 if( grid_count == 1 ) entry->gridinfo = gridlist[0]; } return entry->gridinfo; }