Beispiel #1
0
static int location(grib_handle* h,int n,double *lat,double* lon)
{

    int err=0;
    grib_iterator*  iter =     grib_iterator_new(h,0,&err);
    int i = 0;
    double val;

    if(!iter)
        return 0;


    while(grib_iterator_next(iter,lat,lon,&val))
    {
        if(i++ == n)
        {
            grib_iterator_delete(iter);
            return 1;
        }
    }

    grib_iterator_delete(iter);
    return 0;

}
static int    unpack_double   (grib_accessor* a, double* val, size_t *len)
{
    grib_context* c=a->context;
    int ret = 0;
    double* v=val;
    double lat,lon,value;
    size_t size=0;
    long count=0;
    grib_iterator* iter=grib_iterator_new(grib_handle_of_accessor(a),0,&ret);
    if (ret!=GRIB_SUCCESS) {
        if (iter) grib_iterator_delete(iter);
        grib_context_log(c,GRIB_LOG_ERROR,"unable to create iterator");
        return ret;
    }

    size=0;
    ret=value_count(a,&count);
    if (ret) return ret;
    size=count;

    if (*len<size) {
        if (iter) grib_iterator_delete(iter);
        return GRIB_ARRAY_TOO_SMALL;
    }

    while(grib_iterator_next(iter,&lat,&lon,&value)) {
        *(v++)=lat;*(v++)=lon;*(v++)=value;
    }

    grib_iterator_delete(iter);

    *len=size;

    return ret;
}
static int get_distinct(grib_accessor* a,double** val,long* len) {
  long count=0;
  double prev;
  double *v=NULL;
  double *v1=NULL;
  double dummy;
  int ret=0;
  int i;
  size_t size=*len;
  grib_context* c=a->parent->h->context;
  grib_iterator* iter=grib_iterator_new(a->parent->h,0,&ret);
  if (ret!=GRIB_SUCCESS) {
    if (iter) grib_iterator_delete(iter);
    grib_context_log(c,GRIB_LOG_ERROR,"unable to create iterator");
    return ret;
  }
  v=(double*)grib_context_malloc_clear(c,size*sizeof(double));
  if (!v) {
    grib_context_log(c,GRIB_LOG_ERROR,
          "unable to allocate %ld bytes",(long)size*sizeof(double));
    return GRIB_OUT_OF_MEMORY;
  }
  *val=v;

  while(grib_iterator_next(iter,v++,&dummy,&dummy)) {}
  grib_iterator_delete(iter);
  v=*val;
  qsort(v,*len,sizeof(double),&compare_doubles);


  v1=(double*)grib_context_malloc_clear(c,size*sizeof(double));
  if (!v1) {
    grib_context_log(c,GRIB_LOG_ERROR,
          "unable to allocate %ld bytes",(long)size*sizeof(double));
    return GRIB_OUT_OF_MEMORY;
  }

  prev=v[0];
  v1[0]=prev;
  count=1;
  for (i=1;i<*len;i++) {
    if (v[i]!=prev) {
      prev=v[i];
      v1[count]=prev;
      count++;
    }
  }

  grib_context_free(c,v);

  *val=v1;

  *len=count;
  return GRIB_SUCCESS;
}
Beispiel #4
0
int grib_get_data(grib_handle* h,double* lats, double* lons,double* values)
{
    int err=0;
    grib_iterator* iter=NULL;
    double *lat,*lon,*val;

    iter=grib_iterator_new(h,0,&err);
    if (!iter || err!=GRIB_SUCCESS) return err;

    lat=lats; lon=lons; val=values;
    while(grib_iterator_next(iter,lat++,lon++,val++)) {}

    grib_iterator_delete( iter);

    return err;
}
static int    unpack_double   (grib_accessor* a, double* val, size_t *len)
{
  grib_context* c=a->parent->h->context;
  grib_accessor_latitudes* self = (grib_accessor_latitudes*)a;
  int ret = 0;
  double* v=val;
  double dummy=0;
  size_t size=0;
  grib_iterator* iter=NULL;

  self->save=1;
  size=value_count(a);
  if (*len<size) return GRIB_ARRAY_TOO_SMALL;
  self->save=0;

  /* self->lats are computed in _value_count*/
  if (self->lats) {
    int i;
    *len=self->size;
    for (i=0;i<size;i++) val[i]=self->lats[i];
    grib_context_free(c,self->lats);
    self->lats=NULL;
    self->size=0;
    return GRIB_SUCCESS;
  }

  iter=grib_iterator_new(a->parent->h,0,&ret);
  if (ret!=GRIB_SUCCESS) {
    if (iter) grib_iterator_delete(iter);
    grib_context_log(c,GRIB_LOG_ERROR,"unable to create iterator");
    return ret;
  }

  while(grib_iterator_next(iter,v++,&dummy,&dummy)) {}
  grib_iterator_delete(iter);

  *len=size;

  return ret;
}
Beispiel #6
0
void InputGrib::getLocationsCore(std::vector<Location>& iLocations) const {
#ifdef WITH_GRIB
   std::string filename = getLocationFilename();
   FILE* fid = fopen(filename.c_str(),"r");
   if(!fid) {
      Global::logger->write("No sample file available for Grib", Logger::error);
   }
   else {
      int err = 0;
      grib_handle* h = grib_handle_new_from_file(0,fid,&err);
      if (h == NULL) {
         std::stringstream ss;
         ss << "Unable to create handle from file " << filename;
         Global::logger->write(ss.str(),Logger::error);
      }

      // Iterate over all locations
      grib_iterator* iter=grib_iterator_new(h,0,&err);                                     
      if (err != GRIB_SUCCESS) GRIB_CHECK(err,0);                       
      int id = 0;
      double lat, lon;
      double value;
      while(grib_iterator_next(iter,&lat,&lon,&value)) {   
         float elev = 0;//elevs[i];
         assert(lat <= 90 && lat >= -90);
         Location loc(getName(), id, lat, lon);
         loc.setElev(elev);
         iLocations.push_back(loc);
         id++;
      }
      grib_iterator_delete(iter);
      grib_handle_delete(h);
   }
   fclose(fid);
#else
    Global::logger->write("InputGrib: Program not compiled with GRIB", Logger::error);
#endif
}
Beispiel #7
0
int codes_grib_iterator_next(grib_iterator *i, double* lat,double* lon,double* value)
{
    return grib_iterator_next(i,lat,lon,value);
}
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;
}
Beispiel #9
0
int main(int argc, char* argv[]) {
	grib_handle *h1,*h2;
	int ret=0;
	FILE *f1,*f2;
	char* infile1;
	char* infile2;
	double *v1,*v2,*v,*gv;
	double *lon1,*lon2,*lon,*glon;
	double *lat1,*lat2,*lat,*glat;
	size_t size1,size2,size,gsize;
	double err1,err2,err;
	int i,j;
	grib_context* c;
	grib_iterator *iter1,*iter2;

	c=grib_context_get_default();

	if (argc < 3) usage(argv[0]);

	infile1=argv[1];
	infile2=argv[2];

	f1=fopen(infile1,"r");
	if (!f1) {
		perror(infile1);
		exit(1);
	}

	f2=fopen(infile2,"r");
	if (!f2) {
		perror(infile2);
		exit(1);
	}

	while ((h1=grib_handle_new_from_file(0,f1,&ret))!=NULL) {
		if ((h2=grib_handle_new_from_file(c,f2,&ret))==NULL) {
			printf("unable to create handle from file %s\n",infile2);
			GRIB_CHECK(ret,0);
			exit(1);
		}
		GRIB_CHECK(grib_get_size(h1,"values",&size1),0);
		v1=malloc(size1*sizeof(double));
		if (!v1) {printf("unable to allocate v1\n");exit(1);}
		lat1=malloc(size1*sizeof(double));
		if (!lat1) {printf("unable to allocate lat1\n");exit(1);}
		lon1=malloc(size1*sizeof(double));
		if (!lon1) {printf("unable to allocate lon1\n");exit(1);}
		GRIB_CHECK(grib_get_double(h1,"packingError",&err1),0);

		iter1=grib_iterator_new(h1,0,&ret);
		GRIB_CHECK(ret,0);

		GRIB_CHECK(grib_get_size(h2,"values",&size2),0);
		v2=malloc(size2*sizeof(double));
		if (!v2) {printf("unable to allocate v2\n");exit(1);}
		lat2=malloc(size2*sizeof(double));
		if (!lat2) {printf("unable to allocate lat2\n");exit(1);}
		lon2=malloc(size2*sizeof(double));
		if (!lon2) {printf("unable to allocate lon2\n");exit(1);}
		GRIB_CHECK(grib_get_double(h2,"packingError",&err2),0);

		iter2=grib_iterator_new(h2,0,&ret);
		GRIB_CHECK(ret,0);

		lat=lat1; lon=lon1; v=v1;
		while(grib_iterator_next(iter1,lat,lon,v)) {
				lat++;
				if (*lon < 0 ) *lon+=360;
				lon++;
				v++;
			}
		lat=lat2; lon=lon2; v=v2;
		while(grib_iterator_next(iter2,lat,lon,v)) {
				lat++;
				if (*lon < 0 ) *lon+=360;
				lon++;
				v++;
			}

		if (size1 > size2) {
			lat=lat2;lon=lon2;v=v2;
			size=size2;
			glat=lat1;glon=lon1;gv=v1;
			gsize=size1;
		} else {
			lat=lat1;lon=lon1;v=v1;
			size=size1;
			glat=lat2;glon=lon2;gv=v2;
			gsize=size2;
		}
		if (err1>err2) err=err1;
		else err=err2;

		j=0;
		for (i=0;i<size;i++) {
			while (j < gsize && ( lat[i]!=glat[j] || lon[i]!=glon[j] ) ) j++;
			if (j == gsize) {
				j=0;
				while (j < gsize && ( lat[i]!=glat[j] || lon[i]!=glon[j] ) ) j++;
			}
			if (j==gsize) {
				printf("lat=%g lon=%g not found in global\n",lat[i],lon[i]);
				exit(1);
			}
			if (fabs(v[i]-gv[j])>err) {
				ret=1;
				printf("lat=%g lon=%g  sub area value=%g global value=%g\n",
					lat[i],lon[i],v[i],gv[j]);
			}

		}
		free(v);free(gv);free(lat);free(glat);free(lon);free(glon);

	}

	fclose(f1);
	fclose(f2);

	return ret;
}
Beispiel #10
0
int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h) {
  int err=0;
  double *lat=0,*lon=0,*val=0;
  double missing_value=9999.;
  int skip_missing=1;
  char *kmiss=NULL, *p=NULL;
  char *missing_string=NULL;
  int i=0;
  grib_values* values=NULL;
  grib_iterator* iter = NULL;
  char* format=NULL;
  char* default_format="%.10e";
  int print_keys=grib_options_on("p:");
  long numberOfPoints=0;
  double *data_values=0,*lats=0,*lons=0;
  int n = 0;
  size_t size=0;

  if (grib_options_on("F:"))
    format=grib_options_get_option("F:");
  else
    format=default_format;

  if ((err=grib_get_long(h,"numberOfPoints",&numberOfPoints)) !=GRIB_SUCCESS) {
    fprintf(dump_file,"ERROR: unable to get number of points\n");
    return err;
  }

  iter=grib_iterator_new(h,0,&err);

  data_values=(double*)calloc(numberOfPoints+1,sizeof(double));

  if (iter) {
    lats=(double*)calloc(numberOfPoints+1,sizeof(double));
    lons=(double*)calloc(numberOfPoints+1,sizeof(double));
    lat=lats; lon=lons; val=data_values;
    while(grib_iterator_next(iter,lat++,lon++,val++)) {}
  } else if (err==GRIB_NOT_IMPLEMENTED || err==GRIB_SUCCESS){
    size=numberOfPoints;
    grib_get_double_array(h,"values",data_values,&size);
    if (size!=numberOfPoints) {
      if (!grib_options_on("q"))
       fprintf(dump_file,"ERROR: wrong number of points %d\n",(int)numberOfPoints);
      if (grib_options_on("f")) exit(1);
    }
  } else {
    grib_context_log(h->context,GRIB_LOG_ERROR,
                           "%s",grib_get_error_message(err));
    exit(err);
  }

  skip_missing=1;
  if (grib_options_on("m:")) {
    char* end=0;
    double mval=0;
    skip_missing=0;
    kmiss=grib_options_get_option("m:");
    p=kmiss;
    while (*p != ':' && *p != '\0') p++;
    if (*p == ':' && *(p+1) != '\0') {
      *p='\0';
      missing_string=strdup(p+1);
    } else {
      missing_string=strdup(kmiss);
    }
    mval=strtod(kmiss,&end);
    if (end==NULL) missing_value=mval;
    grib_set_double(h,"missingValue",missing_value);
  }

  if (iter)
    fprintf(dump_file,"Latitude, Longitude, ");

  fprintf(dump_file,"Value");

  if (print_keys)
    for (i=0;i<options->print_keys_count; i++)
      fprintf(dump_file,", %s",options->print_keys[i].name);

  fprintf(dump_file,"\n");

  if (print_keys)
    values=get_key_values(options,h);

  if (skip_missing==0){
    for (i=0;i<numberOfPoints;i++) {
      if (iter) fprintf(dump_file,"%9.3f%9.3f ",lats[i],lons[i]);

      if (data_values[i] == missing_value)
        fprintf(dump_file,"%s",missing_string);
      else
        fprintf(dump_file,format,data_values[i]);

      if (print_keys)
        print_key_values(values,options->print_keys_count);
      fprintf(dump_file,"\n");
      n++;
    }

  } else if ( skip_missing==1 ){
    for (i=0;i<numberOfPoints;i++) {
      if (data_values[i] != missing_value){
        if (iter) fprintf(dump_file,"%9.3f%9.3f ",lats[i],lons[i]);
        fprintf(dump_file,format,data_values[i]);
        if (print_keys)
          print_key_values(values,options->print_keys_count);
        fprintf(dump_file,"\n");
        n++;
      }
    }
  }

  if (iter) grib_iterator_delete(iter);

  free(data_values);
  if (iter) {
    free(lats);
    free(lons);
  }

  return 0;
}
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;
}