static int unpack_double_element(grib_accessor* a, size_t idx,double* val) { grib_accessor_data_apply_boustrophedonic_bitmap* self = (grib_accessor_data_apply_boustrophedonic_bitmap*)a; int err = 0,i=0; size_t cidx=0; double missing_value = 0; double* bvals=NULL; size_t n_vals = 0; long nn=0; err=grib_value_count(a,&nn); n_vals=nn; if (err) return err; if(!grib_find_accessor(a->parent->h,self->bitmap)) return grib_get_double_element_internal(a->parent->h,self->coded_values,idx,val); if((err = grib_get_double_internal(a->parent->h,self->missing_value,&missing_value)) != GRIB_SUCCESS) return err; if((err = grib_get_double_element_internal(a->parent->h,self->bitmap,idx,val)) != GRIB_SUCCESS) return err; if (*val == 0) {*val=missing_value;return GRIB_SUCCESS;} bvals = (double*)grib_context_malloc(a->parent->h->context,n_vals*sizeof(double)); if(bvals == NULL) return GRIB_OUT_OF_MEMORY; if((err = grib_get_double_array_internal(a->parent->h,self->bitmap,bvals,&n_vals)) != GRIB_SUCCESS) return err; cidx=0; for (i=0;i<idx;i++) {cidx+=bvals[i];} grib_context_free(a->parent->h->context,bvals); return grib_get_double_element_internal(a->parent->h,self->coded_values,cidx,val); }
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_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; }