/** * Copyright 2005-2007 ECMWF * * Licensed under the GNU Lesser General Public License which * incorporates the terms and conditions of version 3 of the GNU * General Public License. * See LICENSE and gpl-3.0.txt for details. */ /** * Author: Enrico Fucile * date: 31/10/2007 * */ #include "grib_api_internal.h" int grib_nearest_find(grib_nearest *nearest,grib_handle* h,double inlat,double inlon, unsigned long flags,double* outlats,double* outlons, double* values,double* distances, int* indexes, size_t *len) { grib_nearest_class *c = nearest->cclass; while(c) { grib_nearest_class *s = c->super ? *(c->super) : NULL; if(c->find) { int ret=c->find(nearest,h,inlat,inlon,flags,outlats,outlons,values,distances,indexes,len); if (ret!=GRIB_SUCCESS) { if (inlon>0) inlon-=360; else inlon+=360; ret=c->find(nearest,h,inlat,inlon,flags,outlats,outlons,values,distances,indexes,len); } return ret; } c = s; } Assert(0); return 0; } /* For this one, ALL init are called */ static int init_nearest(grib_nearest_class* c,grib_nearest* i, grib_handle *h, grib_arguments* args) { if(c) { int ret = GRIB_SUCCESS; grib_nearest_class *s = c->super ? *(c->super) : NULL; if(!c->inited) { if(c->init_class) c->init_class(c); c->inited = 1; } if(s) ret = init_nearest(s,i,h,args); if(ret != GRIB_SUCCESS) return ret; if(c->init) return c->init(i,h, args); } return GRIB_INTERNAL_ERROR; } int grib_nearest_init(grib_nearest* i, grib_handle *h, grib_arguments* args) { return init_nearest(i->cclass,i,h,args); } /* For this one, ALL destroy are called */ int grib_nearest_delete(grib_nearest *i) { grib_nearest_class *c = i->cclass; while(c) { grib_nearest_class *s = c->super ? *(c->super) : NULL; if(c->destroy) c->destroy(i); c = s; } return 0; } void grib_binary_search(double xx[], const unsigned long n, double x, int *ju,int *jl) { size_t jm=0; int ascending=0; *jl=0; *ju=n; ascending=(xx[n] >= xx[0]); while (*ju-*jl > 1) { jm=(*ju+*jl) >> 1; if ((x >= xx[jm]) == ascending) *jl=jm; else *ju=jm; } } #define RADIAN(x) ((x) * acos(0.0) / 90.0) double grib_nearest_distance(double radius,double lon1, double lat1, double lon2, double lat2){ double rlat1=RADIAN(lat1); double rlat2=RADIAN(lat2); double rlon1=lon1; double rlon2=lon2; double a; if (rlon1 >=360) rlon1-=360.0; rlon1=RADIAN(rlon1); if (rlon2 >=360) rlon2-=360.0; rlon2=RADIAN(rlon2); a = sin(rlat1)*sin(rlat2)+ cos(rlat1)*cos(rlat2)*cos(rlon2-rlon1); if (a > 1 || a < -1 ) a=(int)a; return radius*acos(a); } int grib_nearest_find_multiple(grib_handle* h,int is_lsm, double* inlats,double* inlons,long npoints, double* outlats,double* outlons, double* values,double* distances, int* indexes) { grib_nearest* nearest=0; double* pdistances=distances; double* poutlats=outlats; double* poutlons=outlons; double* pvalues=values; int* pindexes=indexes; int idx=0,ii=0; double max,min; double qdistances[4]={0,}; double qoutlats[4]={0,}; double qoutlons[4]={0,}; double qvalues[4]={0,}; int qindexes[4]={0,}; int ret=0; long i=0; size_t len=4; int flags=GRIB_NEAREST_SAME_GRID | GRIB_NEAREST_SAME_DATA; nearest=grib_nearest_new(h,&ret); if (ret!=GRIB_SUCCESS) return ret; if (is_lsm) { int noland=1; for (i=0;i= 0.5) noland=0; } min=max; for (ii=0;ii<4;ii++) { if ((min >= qdistances[ii]) && ( noland || (qvalues[ii] >= 0.5)) ) { min = qdistances[ii]; idx=ii; } } *poutlats=qoutlats[idx];poutlats++; *poutlons=qoutlons[idx];poutlons++; *pvalues=qvalues[idx];pvalues++; *pdistances=qdistances[idx];pdistances++; *pindexes=qindexes[idx];pindexes++; } } else { for (i=0;i= qdistances[ii])) { min = qdistances[ii]; idx=ii; } } *poutlats=qoutlats[idx];poutlats++; *poutlons=qoutlons[idx];poutlons++; *pvalues=qvalues[idx];pvalues++; *pdistances=qdistances[idx];pdistances++; *pindexes=qindexes[idx];pindexes++; } } grib_nearest_delete(nearest); return ret; }