static int 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_latlon_reduced* self = (grib_nearest_latlon_reduced*) nearest; int ret=0,kk=0,ii=0,jj=0; int j=0; long* pla=NULL; long* pl=NULL; size_t nvalues=0; grib_iterator* iter=NULL; double lat=0,lon=0; long iradius; double radius; int ilat=0,ilon=0; if( (ret = grib_get_size(h,self->values_key,&nvalues))!= GRIB_SUCCESS) return ret; nearest->values_count = nvalues; if (grib_is_missing(h,self->radius,&ret)) { grib_context_log(h->context, GRIB_LOG_DEBUG,"Key '%s' is missing", self->radius); return ret ? ret : GRIB_GEOCALCULUS_PROBLEM; } if( (ret = grib_get_long(h,self->radius,&iradius))!= GRIB_SUCCESS) return ret; radius=((double)iradius)/1000.0; if (!nearest->h || (flags & GRIB_NEAREST_SAME_GRID)==0) { double dummy=0; double olat=1.e10; long n=0; ilat=0,ilon=0; if (grib_is_missing(h,self->Nj,&ret)) { grib_context_log(h->context, GRIB_LOG_DEBUG,"Key '%s' is missing", self->Nj); return ret ? ret : GRIB_GEOCALCULUS_PROBLEM; } if( (ret = grib_get_long(h,self->Nj,&n))!= GRIB_SUCCESS) return ret; self->lats_count=n; if (self->lats) grib_context_free(nearest->context,self->lats); self->lats=(double*)grib_context_malloc( nearest->context, self->lats_count* sizeof(double)); if (!self->lats) return GRIB_OUT_OF_MEMORY; if (self->lons) grib_context_free(nearest->context,self->lons); self->lons=(double*)grib_context_malloc( nearest->context, nearest->values_count*sizeof(double)); if (!self->lons) return GRIB_OUT_OF_MEMORY; iter=grib_iterator_new(h,0,&ret); if (ret) { grib_context_log(h->context,GRIB_LOG_ERROR,"unable to create iterator"); return ret; } while(grib_iterator_next(iter,&lat,&lon,&dummy)) { if (olat!=lat) { self->lats[ilat++]=lat; olat=lat; } self->lons[ilon++]=lon; } self->lats_count=ilat; grib_iterator_delete(iter); } nearest->h=h; if (!self->distances || (flags & GRIB_NEAREST_SAME_POINT)==0 || (flags & GRIB_NEAREST_SAME_GRID)==0) { double* lons=NULL; int nlon=0; size_t plsize=0; long nplm1=0; int nearest_lons_found=0; double lon_first,lon_last; int islocal=0; long plmax; double dimin; if ((ret=grib_get_double(h,self->lonFirst,&lon_first))!=GRIB_SUCCESS) { grib_context_log(h->context,GRIB_LOG_ERROR, "grib_nearest_latlon_reduced.find(): unable to get %s %s\n",self->lonFirst, grib_get_error_message(ret)); return ret; } if ((ret=grib_get_double(h,self->lonLast,&lon_last))!=GRIB_SUCCESS) { grib_context_log(h->context,GRIB_LOG_ERROR, "grib_nearest_latlon_reduced.find(): unable to get %s %s\n",self->lonLast, grib_get_error_message(ret)); return ret; } plsize=self->lats_count; if( (ret=grib_get_size(h,self->pl,&plsize))!= GRIB_SUCCESS) return ret; pla=(long*)grib_context_malloc(h->context,plsize*sizeof(long)); if (!pla) return GRIB_OUT_OF_MEMORY; if( (ret=grib_get_long_array(h,self->pl,pla,&plsize))!= GRIB_SUCCESS) return ret; pl=pla; while ((*pl)==0) {pl++;} plmax=pla[0]; for (j=0;j<plsize;j++) if (plmax<pla[j]) plmax=pla[j]; dimin=360.0/plmax; if ( 360-fabs(lon_last-lon_first) < 2 * dimin ) {islocal=0;} else {islocal=1;} if (islocal) for (j=0;j<plsize;j++) pla[j]--; /* printf("XXXX islocal=%d\n",islocal); */ while (inlon<0) inlon+=360; while (inlon>360) inlon-=360; ilat=self->lats_count; if (self->lats[ilat-1] > self->lats[0]) { if (inlat < self->lats[0] || inlat > self->lats[ilat-1]) return GRIB_OUT_OF_AREA; } else { if (inlat > self->lats[0] || inlat < self->lats[ilat-1]) return GRIB_OUT_OF_AREA; } if (!self->distances) self->distances=(double*)grib_context_malloc( nearest->context,4*sizeof(double)); if (!self->distances) return GRIB_OUT_OF_MEMORY; grib_binary_search(self->lats,ilat-1,inlat, &(self->j[0]),&(self->j[1])); nlon=0; for (jj=0;jj<self->j[0];jj++) nlon+=pl[jj]; nplm1=pl[self->j[0]]-1; lons=self->lons+nlon; nearest_lons_found=0; if (lons[nplm1]>lons[0]) { if (inlon< lons[0] || inlon > lons[nplm1]) { if (lons[nplm1]-lons[0]-360 <= lons[nplm1]-lons[nplm1-1]) { self->k[0]=0; self->k[1]=nplm1; nearest_lons_found=1; } else return GRIB_OUT_OF_AREA; } } else { if (inlon >lons[0] || inlon< lons[nplm1]) { if (lons[0]-lons[nplm1]-360 <= lons[0]-lons[1]) { self->k[0]=0; self->k[1]=nplm1; nearest_lons_found=1; } else return GRIB_OUT_OF_AREA; } } if (!nearest_lons_found) { grib_binary_search(lons,pl[self->j[0]]-1,inlon, &(self->k[0]),&(self->k[1])); } self->k[0]+=nlon; self->k[1]+=nlon; nlon=0; for (jj=0;jj<self->j[1];jj++) nlon+=pl[jj]; nplm1=pl[self->j[1]]-1; lons=self->lons+nlon; nearest_lons_found=0; if (lons[nplm1]>lons[0]) { if (inlon<lons[0] || inlon>lons[nplm1]) { if (lons[nplm1]-lons[0]-360 <= lons[nplm1]-lons[nplm1-1]) { self->k[2]=0; self->k[3]=nplm1; nearest_lons_found=1; } else return GRIB_OUT_OF_AREA; } } else { if (inlon>lons[0] || inlon<lons[nplm1]) { if (lons[0]-lons[nplm1]-360 <= lons[0]-lons[1]) { self->k[2]=0; self->k[3]=nplm1; nearest_lons_found=1; } else return GRIB_OUT_OF_AREA; } } if (!nearest_lons_found) { grib_binary_search(lons,pl[self->j[1]]-1,inlon, &(self->k[2]),&(self->k[3])); } self->k[2]+=nlon; self->k[3]+=nlon; kk=0; for (jj=0;jj<2;jj++) { for (ii=0;ii<2;ii++) { self->distances[kk]=grib_nearest_distance(radius,inlon,inlat, self->lons[self->k[kk]],self->lats[self->j[jj]]); kk++; } } grib_context_free(h->context,pla); } kk=0; for (jj=0;jj<2;jj++) { for (ii=0;ii<2;ii++) { distances[kk]=self->distances[kk]; outlats[kk]=self->lats[self->j[jj]]; outlons[kk]=self->lons[self->k[kk]]; grib_get_double_element_internal(h,self->values_key,self->k[kk],&(values[kk])); indexes[kk]=self->k[kk]; kk++; } } return GRIB_SUCCESS; }
static int 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_lambert_conformal* self = (grib_nearest_lambert_conformal*) nearest; int ret=0, i=0; size_t nvalues=0; long iradius; double radius; grib_iterator* iter=NULL; double lat=0,lon=0; /* array of candidates for nearest neighbours */ PointStore* neighbours = NULL; while (inlon<0) inlon+=360; while (inlon>360) inlon-=360; if( (ret = grib_get_size(h,self->values_key,&nvalues))!= GRIB_SUCCESS) return ret; nearest->values_count = nvalues; if (grib_is_missing(h,self->radius,&ret)) { grib_context_log(h->context, GRIB_LOG_DEBUG,"Key '%s' is missing", self->radius); return ret ? ret : GRIB_GEOCALCULUS_PROBLEM; } if( (ret = grib_get_long(h,self->radius,&iradius))!= GRIB_SUCCESS) return ret; radius=((double)iradius)/1000.0; neighbours = (PointStore*)grib_context_malloc( nearest->context, nvalues*sizeof(PointStore) ); for(i=0; i<nvalues; ++i) { neighbours[i].m_dist = 1e10; /* set all distances to large number to begin with */ neighbours[i].m_lat=0; neighbours[i].m_lon=0; neighbours[i].m_value=0; neighbours[i].m_index=0; } /* GRIB_NEAREST_SAME_GRID not yet implemented */ { double the_value = 0; double min_dist = 1e10; size_t the_index = 0; int ilat=0, ilon=0; int idx_upper=0, idx_lower=0; double lat1=0, lat2=0; /* inlat will be between these */ double dist=0; const double LAT_DELTA = 10.0; /* in degrees */ if (grib_is_missing(h,self->Ni,&ret)) { grib_context_log(h->context, GRIB_LOG_DEBUG,"Key '%s' is missing", self->Ni); return ret ? ret : GRIB_GEOCALCULUS_PROBLEM; } if (grib_is_missing(h,self->Nj,&ret)) { grib_context_log(h->context, GRIB_LOG_DEBUG,"Key '%s' is missing", self->Nj); return ret ? ret : GRIB_GEOCALCULUS_PROBLEM; } self->lons_count=nvalues; /* Maybe overestimate but safe */ self->lats_count=nvalues; if (self->lats) grib_context_free(nearest->context,self->lats); self->lats=(double*)grib_context_malloc( nearest->context, nvalues* sizeof(double)); if (!self->lats) return GRIB_OUT_OF_MEMORY; if (self->lons) grib_context_free(nearest->context,self->lons); self->lons=(double*)grib_context_malloc( nearest->context, nvalues*sizeof(double)); if (!self->lons) return GRIB_OUT_OF_MEMORY; iter=grib_iterator_new(h,0,&ret); if (ret) return ret; /* First pass: collect all latitudes and longitudes */ while(grib_iterator_next(iter,&lat,&lon,&the_value)) { ++the_index; Assert(ilat < self->lats_count); Assert(ilon < self->lons_count); self->lats[ilat++]=lat; self->lons[ilon++]=lon; } /* See between which 2 latitudes our point lies */ qsort(self->lats, nvalues, sizeof(double), &compare_doubles_ascending); grib_binary_search(self->lats, self->lats_count-1, inlat, &idx_upper, &idx_lower); lat2 = self->lats[idx_upper]; lat1 = self->lats[idx_lower]; Assert(lat1<=lat2); /* Second pass: Iterate again and collect candidate neighbours */ grib_iterator_reset(iter); the_index=0; i = 0; while(grib_iterator_next(iter,&lat,&lon,&the_value)) { if (lat > lat2+LAT_DELTA || lat < lat1-LAT_DELTA) { /* Ignore latitudes too far from our point */ } else { dist = grib_nearest_distance(radius, inlon, inlat, lon, lat); if (dist < min_dist) min_dist = dist; /*printf("Candidate: lat=%.5f lon=%.5f dist=%f Idx=%ld Val=%f\n",lat,lon,dist,the_index,the_value);*/ /* store this candidate point */ neighbours[i].m_dist = dist; neighbours[i].m_index = the_index; neighbours[i].m_lat = lat; neighbours[i].m_lon = lon; neighbours[i].m_value = the_value; i++; } ++the_index; } /* Sort the candidate neighbours in ascending order of distance */ /* The first 4 entries will now be the closest 4 neighbours */ qsort(neighbours, nvalues, sizeof(PointStore), &compare_points); grib_iterator_delete(iter); } nearest->h=h; /* Sanity check for sorting */ #ifdef DEBUG for(i=0; i<nvalues-1; ++i) { Assert( neighbours[i].m_dist <= neighbours[i+1].m_dist); } #endif /* GRIB_NEAREST_SAME_XXX not yet implemented */ if (!self->distances) { self->distances=(double*)grib_context_malloc( nearest->context,4*sizeof(double)); } self->distances[0] = neighbours[0].m_dist; self->distances[1] = neighbours[1].m_dist; self->distances[2] = neighbours[2].m_dist; self->distances[3] = neighbours[3].m_dist; for(i=0; i <4; ++i) { distances[i] = neighbours[i].m_dist; outlats[i] = neighbours[i].m_lat; outlons[i] = neighbours[i].m_lon; indexes[i] = neighbours[i].m_index; values[i] = neighbours[i].m_value; /*printf("(%f,%f) i=%d d=%f v=%f\n",outlats[i],outlons[i],indexes[i],distances[i],values[i]);*/ } free(neighbours); return GRIB_SUCCESS; }
static int find(grib_nearest* nearest, grib_handle* h, double inlat, double inlon,unsigned long flags, double* outlats,double* outlons, double *values, double *distances,double *distances,int *indexes,size_t *len) { grib_nearest_reduced* self = (grib_nearest_reduced*) nearest; int ret=0,kk=0,ii=0,jj=0; double* pl=NULL; int ilat; size_t nvalues=0; if (!nearest->h || (flags & GRIB_NEAREST_SAME_DATA)==0 || nearest->h!=h) { grib_iterator* iter=NULL; double lat=0,lon=0; if( (ret = grib_get_size(h,self->values_key,&nvalues))!= GRIB_SUCCESS) return ret; nearest->values_count = nvalues; if (nearest->values) grib_context_free(nearest->context,nearest->values); nearest->values = grib_context_malloc(h->context,nvalues*sizeof(double)); if (!nearest->values) return GRIB_OUT_OF_MEMORY; ret=grib_get_double_array_internal( h,self->values_key, nearest->values,&(nearest->values_count)); if (ret!=GRIB_SUCCESS) grib_context_log(nearest->context,GRIB_LOG_ERROR, "nearest: unable to get values array"); if (!nearest->h || (flags & GRIB_NEAREST_SAME_GRID)==0) { double dummy=0; double olat=1.e10; ilat=0,ilon=0; long n=0; if (grib_is_missing(h,self->Nj,&ret)) { grib_context_log(h->context, GRIB_LOG_DEBUG,"Key '%s' is missing", self->Nj); return ret ? ret : GRIB_GEOCALCULUS_PROBLEM; } if( (ret = grib_get_long(h,self->Nj,&n))!= GRIB_SUCCESS) return ret; self->lats_count=n; if (self->lats) grib_context_free(nearest->context,self->lats); self->lats=grib_context_malloc( nearest->context, self->lats_count* sizeof(double)); if (!self->lats) return GRIB_OUT_OF_MEMORY; if (self->lons) grib_context_free(nearest->context,self->lons); self->lons=grib_context_malloc( nearest->context, nearest->values_count*sizeof(double)); if (!self->lons) return GRIB_OUT_OF_MEMORY; iter=grib_iterator_new(h,0,&ret); while(grib_iterator_next(iter,&lat,&lon,&dummy)) { if (olat!=lat) {self->lats[ilat++]=lat;olat=lat;} self->lons[ilon++]=lon; } grib_iterator_delete(iter); } nearest->h=h; } if (!self->distances || (flags & GRIB_NEAREST_SAME_POINT)==0 || (flags & GRIB_NEAREST_SAME_GRID)==0) { double* lons=NULL; int nlon=0; int plsize=0; self->distances=(double*)grib_context_malloc( nearest->context,4*sizeof(double)); if (!self->distances) return GRIB_OUT_OF_MEMORY; grib_binary_search(self->lats,self->lats_count-1,inlat, &(self->j[0]),&(self->j[1])); plsize=self->lats_count; pl=(double*)grib_context_malloc(h->context,plsize*sizeof(double)); if (!pl) return GRIB_OUT_OF_MEMORY; if( (ret=grib_get_double_array(h,"pl",pl,&plsize))!= GRIB_SUCCESS) return ret; nlon=0; for (jj=0;jj<self->j[0];jj++) { nlon+=pl[jj]; } lons=self->lons+nlon; grib_binary_search(lons,pl[self->j[0]]-1,inlon, &(self->k[0]),&(self->k[1])); self->k[0]+=nlon; self->k[1]+=nlon; nlon=0; for (jj=0;jj<self->j[1];jj++) { nlon+=pl[jj]; } lons=self->lons+nlon; grib_binary_search(lons,pl[self->j[1]]-1,inlon, &(self->k[2]),&(self->k[3])); self->k[2]+=nlon; self->k[3]+=nlon; kk=0; for (ii=0;ii<2;ii++) { for (jj=0;jj<2;jj++) { self->distances[kk]=grib_nearest_distance(radius,inlon,inlat, self->lons[self->k[kk]],self->lats[self->j[jj]]); kk++; } } grib_context_free(h->context,pl); } kk=0; for (ii=0;ii<2;ii++) { for (jj=0;jj<2;jj++) { distances[kk]=self->distances[kk]; outlats[kk]=self->lats[self->j[jj]]; outlons[kk]=self->lons[self->k[kk]]; values[kk]=nearest->values[self->k[kk]]; indexes[kk]=self->k[kk]; kk++; } } return GRIB_SUCCESS; }
static int 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_reduced* self = (grib_nearest_reduced*) nearest; int ret=0,kk=0,ii=0,jj=0; long* pla=NULL; long* pl=NULL; size_t nvalues=0; grib_iterator* iter=NULL; double lat=0,lon=0; long iradius; double radius; int ilat=0,ilon=0; if( (ret = grib_get_size(h,self->values_key,&nvalues))!= GRIB_SUCCESS) return ret; nearest->values_count = nvalues; if (grib_is_missing(h,self->radius,&ret)) { grib_context_log(h->context, GRIB_LOG_DEBUG,"Key '%s' is missing", self->radius); return ret ? ret : GRIB_GEOCALCULUS_PROBLEM; } if( (ret = grib_get_long(h,self->radius,&iradius))!= GRIB_SUCCESS) return ret; radius=((double)iradius)/1000.0; if (!nearest->h || (flags & GRIB_NEAREST_SAME_GRID)==0) { double dummy=0; double olat=1.e10; long n=0; ilat=0,ilon=0; if (grib_is_missing(h,self->Nj,&ret)) { grib_context_log(h->context, GRIB_LOG_DEBUG,"Key '%s' is missing", self->Nj); return ret ? ret : GRIB_GEOCALCULUS_PROBLEM; } if( (ret = grib_get_long(h,self->Nj,&n))!= GRIB_SUCCESS) return ret; self->lats_count=n; if (self->lats) grib_context_free(nearest->context,self->lats); self->lats=(double*)grib_context_malloc( nearest->context, self->lats_count* sizeof(double)); if (!self->lats) return GRIB_OUT_OF_MEMORY; if (self->lons) grib_context_free(nearest->context,self->lons); self->lons=(double*)grib_context_malloc( nearest->context, nearest->values_count*sizeof(double)); if (!self->lons) return GRIB_OUT_OF_MEMORY; iter=grib_iterator_new(h,0,&ret); while(grib_iterator_next(iter,&lat,&lon,&dummy)) { if (olat!=lat) { self->lats[ilat++]=lat; olat=lat; } self->lons[ilon++]=lon; } self->lats_count=ilat; grib_iterator_delete(iter); } nearest->h=h; if (!self->distances || (flags & GRIB_NEAREST_SAME_POINT)==0 || (flags & GRIB_NEAREST_SAME_GRID)==0) { double* lons=NULL; int nlon=0; size_t plsize=0; long nplm1=0; int nearest_lons_found=0; long global=0; double lon_first,lon_last; long row_count,ilon_first,ilon_last; /*TODO global from the def file*/ global=1; grib_get_long(h,"global",&global); if (!global) { /*TODO longitudeOfFirstGridPointInDegrees from the def file*/ if ((ret=grib_get_double(h,"longitudeOfFirstGridPointInDegrees",&lon_first))!=GRIB_SUCCESS) { grib_context_log(h->context,GRIB_LOG_ERROR, "grib_nearest_reduced.find(): unable to get longitudeOfFirstGridPointInDegrees %s\n", grib_get_error_message(ret)); return ret; } /*TODO longitudeOfLastGridPointInDegrees from the def file*/ if ((ret=grib_get_double(h,"longitudeOfLastGridPointInDegrees",&lon_last))!=GRIB_SUCCESS) { grib_context_log(h->context,GRIB_LOG_ERROR, "grib_nearest_reduced.find(): unable to get longitudeOfLastGridPointInDegrees %s\n", grib_get_error_message(ret)); return ret; } /* if (lon_last<0) lon_last+=360; */ /* if (lon_first<0) lon_first+=360; */ } else { while (inlon<0) inlon+=360; while (inlon>360) inlon-=360; } ilat=self->lats_count; if (self->lats[ilat-1] > self->lats[0]) { if (inlat < self->lats[0] || inlat > self->lats[ilat-1]) return GRIB_OUT_OF_AREA; } else { if (inlat > self->lats[0] || inlat < self->lats[ilat-1]) return GRIB_OUT_OF_AREA; } if (!self->distances) self->distances=(double*)grib_context_malloc( nearest->context,4*sizeof(double)); if (!self->distances) return GRIB_OUT_OF_MEMORY; grib_binary_search(self->lats,ilat-1,inlat, &(self->j[0]),&(self->j[1])); plsize=self->lats_count; if( (ret=grib_get_size(h,self->pl,&plsize))!= GRIB_SUCCESS) return ret; pla=(long*)grib_context_malloc(h->context,plsize*sizeof(long)); if (!pla) return GRIB_OUT_OF_MEMORY; if( (ret=grib_get_long_array(h,self->pl,pla,&plsize))!= GRIB_SUCCESS) return ret; pl=pla; while ((*pl)==0) {pl++;} nlon=0; if (global) { for (jj=0;jj<self->j[0];jj++) nlon+=pl[jj]; nplm1=pl[self->j[0]]-1; } else { nlon=0; for (jj=0;jj<self->j[0];jj++) { row_count=0;ilon_first=0;ilon_last=0; grib_get_reduced_row(pl[jj],lon_first,lon_last,&row_count,&ilon_first,&ilon_last); nlon+=row_count; } row_count=0;ilon_first=0;ilon_last=0; grib_get_reduced_row(pl[self->j[0]],lon_first,lon_last,&row_count,&ilon_first,&ilon_last); nplm1=row_count-1; } lons=self->lons+nlon; nearest_lons_found=0; if (lons[nplm1]>lons[0]) { if (inlon< lons[0] || inlon > lons[nplm1]) { if (lons[nplm1]-lons[0]-360 <= lons[nplm1]-lons[nplm1-1]) { self->k[0]=0; self->k[1]=nplm1; nearest_lons_found=1; } else return GRIB_OUT_OF_AREA; } } else { if (inlon >lons[0] || inlon< lons[nplm1]) { if (lons[0]-lons[nplm1]-360 <= lons[0]-lons[1]) { self->k[0]=0; self->k[1]=nplm1; nearest_lons_found=1; } else return GRIB_OUT_OF_AREA; } } if (!nearest_lons_found) { if (!global) { row_count=0;ilon_first=0;ilon_last=0; grib_get_reduced_row(pl[self->j[0]],lon_first,lon_last,&row_count,&ilon_first,&ilon_last); } else { row_count=pl[self->j[0]]; } grib_binary_search(lons,row_count-1,inlon, &(self->k[0]),&(self->k[1])); } self->k[0]+=nlon; self->k[1]+=nlon; nlon=0; if (global) { for (jj=0;jj<self->j[1];jj++) nlon+=pl[jj]; nplm1=pl[self->j[1]]-1; } else { long row_count,ilon_first,ilon_last; for (jj=0;jj<self->j[1];jj++) { row_count=0;ilon_first=0;ilon_last=0; grib_get_reduced_row(pl[jj],lon_first,lon_last,&row_count,&ilon_first,&ilon_last); nlon+=row_count; } row_count=0;ilon_first=0;ilon_last=0; grib_get_reduced_row(pl[self->j[1]],lon_first,lon_last,&nplm1,&ilon_first,&ilon_last); nplm1--; } lons=self->lons+nlon; nearest_lons_found=0; if (lons[nplm1]>lons[0]) { if (inlon<lons[0] || inlon>lons[nplm1]) { if (lons[nplm1]-lons[0]-360 <= lons[nplm1]-lons[nplm1-1]) { self->k[2]=0; self->k[3]=nplm1; nearest_lons_found=1; } else return GRIB_OUT_OF_AREA; } } else { if (inlon>lons[0] || inlon<lons[nplm1]) { if (lons[0]-lons[nplm1]-360 <= lons[0]-lons[1]) { self->k[2]=0; self->k[3]=nplm1; nearest_lons_found=1; } else return GRIB_OUT_OF_AREA; } } if (!nearest_lons_found) { if (!global) { row_count=0;ilon_first=0;ilon_last=0; grib_get_reduced_row(pl[self->j[1]],lon_first,lon_last,&row_count,&ilon_first,&ilon_last); } else { row_count=pl[self->j[1]]; } grib_binary_search(lons,row_count-1,inlon, &(self->k[2]),&(self->k[3])); } self->k[2]+=nlon; self->k[3]+=nlon; kk=0; for (jj=0;jj<2;jj++) { for (ii=0;ii<2;ii++) { self->distances[kk]=grib_nearest_distance(radius,inlon,inlat, self->lons[self->k[kk]],self->lats[self->j[jj]]); kk++; } } grib_context_free(h->context,pla); } kk=0; for (jj=0;jj<2;jj++) { for (ii=0;ii<2;ii++) { distances[kk]=self->distances[kk]; outlats[kk]=self->lats[self->j[jj]]; outlons[kk]=self->lons[self->k[kk]]; grib_get_double_element_internal(h,self->values_key,self->k[kk],&(values[kk])); indexes[kk]=self->k[kk]; kk++; } } return GRIB_SUCCESS; }
static int 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_regular* self = (grib_nearest_regular*) nearest; int ret=0,kk=0,ii=0,jj=0; size_t nvalues=0; long iradius; double radius; grib_iterator* iter=NULL; double lat=0,lon=0; while (inlon<0) inlon+=360; while (inlon>360) inlon-=360; if( (ret = grib_get_size(h,self->values_key,&nvalues))!= GRIB_SUCCESS) return ret; nearest->values_count = nvalues; if (grib_is_missing(h,self->radius,&ret)) { grib_context_log(h->context, GRIB_LOG_DEBUG,"Key '%s' is missing", self->radius); return ret ? ret : GRIB_GEOCALCULUS_PROBLEM; } if( (ret = grib_get_long(h,self->radius,&iradius))!= GRIB_SUCCESS) return ret; radius=((double)iradius)/1000.0; if (!nearest->h || (flags & GRIB_NEAREST_SAME_GRID)==0) { double dummy=0; double olat=1.e10, olon=1.e10; int ilat=0,ilon=0; long n=0; if (grib_is_missing(h,self->Ni,&ret)) { grib_context_log(h->context, GRIB_LOG_DEBUG,"Key '%s' is missing", self->Ni); return ret ? ret : GRIB_GEOCALCULUS_PROBLEM; } if (grib_is_missing(h,self->Nj,&ret)) { grib_context_log(h->context, GRIB_LOG_DEBUG,"Key '%s' is missing", self->Nj); return ret ? ret : GRIB_GEOCALCULUS_PROBLEM; } if ((ret = grib_get_long(h,self->Ni,&n))!= GRIB_SUCCESS) return ret; self->lons_count=n; if ((ret = grib_get_long(h,self->Nj,&n))!= GRIB_SUCCESS) return ret; self->lats_count=n; if (self->lats) grib_context_free(nearest->context,self->lats); self->lats=(double*)grib_context_malloc( nearest->context, self->lats_count* sizeof(double)); if (!self->lats) return GRIB_OUT_OF_MEMORY; if (self->lons) grib_context_free(nearest->context,self->lons); self->lons=(double*)grib_context_malloc( nearest->context, self->lons_count*sizeof(double)); if (!self->lons) return GRIB_OUT_OF_MEMORY; iter=grib_iterator_new(h,0,&ret); while(grib_iterator_next(iter,&lat,&lon,&dummy)) { if (olat != lat) { self->lats[ilat++]=lat; olat=lat; } if (ilon<self->lons_count && olon != lon) { self->lons[ilon++]=lon ; olon=lon; } } grib_iterator_delete(iter); } nearest->h=h; if (!self->distances || (flags & GRIB_NEAREST_SAME_POINT)==0 || (flags & GRIB_NEAREST_SAME_GRID)==0) { int nearest_lons_found=0; if (self->lats[self->lats_count-1] > self->lats[0]) { if (inlat<self->lats[0] || inlat>self->lats[self->lats_count-1]) return GRIB_OUT_OF_AREA; } else { if (inlat > self->lats[0] || inlat < self->lats[self->lats_count-1]) return GRIB_OUT_OF_AREA; } if (self->lons[self->lons_count-1] > self->lons[0]) { if (inlon<self->lons[0] || inlon>self->lons[self->lons_count-1]) { /* try to scale*/ if (inlon>0) inlon-=360; else inlon+=360; if (inlon<self->lons[0] || inlon>self->lons[self->lons_count-1]) { if ( self->lons[0]+360-self->lons[self->lons_count-1]<= self->lons[1]-self->lons[0]) { /*it's a global field in longitude*/ self->i[0]=0; self->i[1]=self->lons_count-1; nearest_lons_found=1; } else return GRIB_OUT_OF_AREA; } } } else { if (inlon>self->lons[0] || inlon<self->lons[self->lons_count-1]) { /* try to scale*/ if (inlon>0) inlon-=360; else inlon+=360; if (self->lons[0]-self->lons[self->lons_count-1]-360 <= self->lons[0]-self->lons[1]) { /*it's a global field in longitude*/ self->i[0]=0; self->i[1]=self->lons_count-1; nearest_lons_found=1; } else if (inlon>self->lons[0] || inlon<self->lons[self->lons_count-1]) return GRIB_OUT_OF_AREA; } } grib_binary_search(self->lats,self->lats_count-1,inlat, &(self->j[0]),&(self->j[1])); if (!nearest_lons_found) grib_binary_search(self->lons,self->lons_count-1,inlon, &(self->i[0]),&(self->i[1])); if (!self->distances) self->distances=(double*)grib_context_malloc( nearest->context,4*sizeof(double)); if (!self->k) self->k=(int*)grib_context_malloc( nearest->context,4*sizeof(int)); kk=0; for (jj=0;jj<2;jj++) { for (ii=0;ii<2;ii++) { self->k[kk]=self->i[ii]+self->lons_count*self->j[jj]; self->distances[kk]=grib_nearest_distance(radius,inlon,inlat, self->lons[self->i[ii]],self->lats[self->j[jj]]); kk++; } } } kk=0; /* * Brute force algorithm: * First unpack all the values into an array. Then when we need the 4 points * we just index into this array so no need to call grib_get_double_element_internal * * if (nearest->values) grib_context_free(nearest->context,nearest->values); * nearest->values = grib_context_malloc(h->context,nvalues*sizeof(double)); * if (!nearest->values) return GRIB_OUT_OF_MEMORY; * ret = grib_get_double_array(h, self->values_key, nearest->values ,&nvalues); * if (ret) return ret; */ for (jj=0;jj<2;jj++) { for (ii=0;ii<2;ii++) { distances[kk]=self->distances[kk]; outlats[kk]=self->lats[self->j[jj]]; outlons[kk]=self->lons[self->i[ii]]; grib_get_double_element_internal(h,self->values_key,self->k[kk],&(values[kk])); /* Using the brute force approach described above */ /* Assert(self->k[kk] < nvalues); */ /* values[kk]=nearest->values[self->k[kk]]; */ indexes[kk]=self->k[kk]; kk++; } } return GRIB_SUCCESS; }
static int 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_regular* self = (grib_nearest_regular*) nearest; int ret=0,kk=0,ii=0,jj=0; size_t nvalues=0; long iradius; double radius; if( (ret = grib_get_long(h,self->radius,&iradius))!= GRIB_SUCCESS) return ret; radius=((double)iradius)/1000.0; if (!nearest->h || (flags & GRIB_NEAREST_SAME_DATA)==0 || nearest->h!=h) { grib_iterator* iter=NULL; double lat=0,lon=0; if( (ret = grib_get_size(h,self->values_key,&nvalues))!= GRIB_SUCCESS) return ret; nearest->values_count = nvalues; if (nearest->values) grib_context_free(nearest->context,nearest->values); nearest->values = grib_context_malloc(h->context,nvalues*sizeof(double)); if (!nearest->values) return GRIB_OUT_OF_MEMORY; ret=grib_get_double_array_internal( h,self->values_key, nearest->values,&(nearest->values_count)); if (ret!=GRIB_SUCCESS) grib_context_log(nearest->context,GRIB_LOG_ERROR, "nearest: unable to get values array"); if (!nearest->h || (flags & GRIB_NEAREST_SAME_GRID)==0) { double dummy=0; double olat=1.e10, olon=1.e10; int ilat=0,ilon=0; long n=0; if( (ret = grib_get_long(h,self->Ni,&n))!= GRIB_SUCCESS) return ret; self->lons_count=n; if( (ret = grib_get_long(h,self->Nj,&n))!= GRIB_SUCCESS) return ret; self->lats_count=n; if (self->lats) grib_context_free(nearest->context,self->lats); self->lats=grib_context_malloc( nearest->context, self->lats_count* sizeof(double)); if (!self->lats) return GRIB_OUT_OF_MEMORY; if (self->lons) grib_context_free(nearest->context,self->lons); self->lons=grib_context_malloc( nearest->context, self->lons_count*sizeof(double)); if (!self->lons) return GRIB_OUT_OF_MEMORY; iter=grib_iterator_new(h,0,&ret); if (ret) { grib_context_log(nearest->context,GRIB_LOG_ERROR,"unable to create iterator"); return ret; } while(grib_iterator_next(iter,&lat,&lon,&dummy)) { if (olat != lat) { self->lats[ilat++]=lat; olat=lat; } if (ilon<self->lons_count && olon != lon) { self->lons[ilon++]=lon; olon=lon; } } grib_iterator_delete(iter); } nearest->h=h; } if (!self->distances || (flags & GRIB_NEAREST_SAME_POINT)==0 || (flags & GRIB_NEAREST_SAME_GRID)==0) { grib_binary_search(self->lats,self->lats_count-1,inlat, &(self->j[0]),&(self->j[1])); grib_binary_search(self->lons,self->lons_count-1,inlon, &(self->i[0]),&(self->i[1])); if (!self->distances) self->distances=(double*)grib_context_malloc( nearest->context,4*sizeof(double)); if (!self->k) self->k=(int*)grib_context_malloc( nearest->context,4*sizeof(int)); kk=0; for (ii=0;ii<2;ii++) { for (jj=0;jj<2;jj++) { self->k[kk]=self->i[ii]+self->lons_count*self->j[jj]-1; self->distances[kk]=grib_nearest_distance(radius,inlon,inlat, self->lons[self->i[ii]],self->lats[self->j[jj]]); kk++; } } } kk=0; for (ii=0;ii<2;ii++) { for (jj=0;jj<2;jj++) { distances[kk]=self->distances[kk]; outlats[kk]=self->lats[self->j[jj]]; outlons[kk]=self->lons[self->i[ii]]; values[kk]=nearest->values[self->k[kk]]; indexes[kk]=self->k[kk]; kk++; } } return GRIB_SUCCESS; }