Beispiel #1
0
void codes_get_reduced_row(long pl,double lon_first,double lon_last,long* npoints,long* ilon_first, long* ilon_last )
{
    grib_get_reduced_row(pl,lon_first,lon_last,npoints,ilon_first,ilon_last);
}
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 init(grib_iterator* iter,grib_handle* h,grib_arguments* args)
{
  int ret=GRIB_SUCCESS,j;
  double lat_first=0,lon_first=0,lat_last=0,lon_last=0,d=0;
  double* lats;
  size_t plsize=0;
  int l=0;
  long* pl;
  long nj=0,order=0,ilon_first,ilon_last,i;
  long row_count=0;
  grib_context* c=h->context;
  grib_iterator_gaussian_reduced* self = (grib_iterator_gaussian_reduced*)iter;
  const char* slat_first   = grib_arguments_get_name(h,args,self->carg++);
  const char* slon_first   = grib_arguments_get_name(h,args,self->carg++);
  const char* slat_last    = grib_arguments_get_name(h,args,self->carg++);
  const char* slon_last    = grib_arguments_get_name(h,args,self->carg++);
  const char* sorder       = grib_arguments_get_name(h,args,self->carg++);
  const char* spl          = grib_arguments_get_name(h,args,self->carg++);
  const char* snj          = grib_arguments_get_name(h,args,self->carg++);

  if((ret = grib_get_double_internal(h, slat_first,&lat_first)) != GRIB_SUCCESS)
    return ret;
  if((ret = grib_get_double_internal(h, slon_first,&lon_first)) != GRIB_SUCCESS)
    return ret;
  if((ret = grib_get_double_internal(h, slat_last,&lat_last)) != GRIB_SUCCESS)
    return ret;
  if((ret = grib_get_double_internal(h, slon_last,&lon_last)) != GRIB_SUCCESS)
    return ret;

  if((ret = grib_get_long_internal(h, sorder,&order)) != GRIB_SUCCESS)
    return ret;
  if((ret = grib_get_long_internal(h, snj,&nj)) != GRIB_SUCCESS)
    return ret;

  lats=(double*)grib_context_malloc(h->context,sizeof(double)*order*2);
  if((ret = grib_get_gaussian_latitudes(order, lats)) != GRIB_SUCCESS)
      return ret;

  if((ret = grib_get_size(h,spl,&plsize)) != GRIB_SUCCESS)
      return ret;

  pl=(long*)grib_context_malloc(c,sizeof(long)*plsize);
  grib_get_long_array_internal(h,spl,pl, &plsize);

  self->las = grib_context_malloc(h->context,iter->nv*sizeof(double));
  self->los = grib_context_malloc(h->context,iter->nv*sizeof(double));

  while (lon_last<0) lon_last+=360;
  while (lon_first<0) lon_first+=360;

  d=fabs(lats[0]-lats[1]);
  if ( (fabs(lat_first-lats[0]) >= d ) ||
       (fabs(lat_last+lats[0]) >= d )  ||
       lon_first != 0                 ||
       fabs(lon_last  - (360.0-90.0/order)) > 90.0/order
       ) {
    /*sub area*/
	/*find starting latitude */
	while (fabs(lat_first-lats[l]) > d ) {l++;}
    iter->e=0;
    for (j=0;j<plsize;j++) {
        row_count=0;
		/*printf("lat=%g\n",lats[j+l]);*/
		grib_get_reduced_row(pl[j],lon_first,lon_last,
                  &row_count,&ilon_first,&ilon_last);
        if (ilon_first>ilon_last) ilon_first-=pl[j];
        for (i=ilon_first;i<=ilon_last;i++) {
         self->los[iter->e]=((i)*360.0)/pl[j];
         self->las[iter->e]=lats[j+l];
         iter->e++;
        }
     }
  } else {
    /*global*/
    iter->e=0;
    for (j=0;j<plsize;j++) {
        row_count=pl[j];
        for (i=0;i<row_count;i++) {
         self->los[iter->e]=(i*360.0)/row_count;
         self->las[iter->e]=lats[j];
         iter->e++;
        }
     }
  }

  iter->e = -1;
  grib_context_free(h->context,lats);
  grib_context_free(h->context,pl);

  return ret;
}
static int init(grib_iterator* iter,grib_handle* h,grib_arguments* args)
{
    int ret=GRIB_SUCCESS, j, is_global=0;
    double lat_first=0,lon_first=0,lat_last=0,lon_last=0;
    double angular_precision = 1.0/1000000.0;
    double* lats;
    size_t plsize=0;
    long* pl;
    long max_pl=0;
    long nj=0,order=0,ilon_first,ilon_last,i;
    long row_count=0;
    long editionNumber = 0;
    grib_context* c=h->context;
    grib_iterator_gaussian_reduced* self = (grib_iterator_gaussian_reduced*)iter;
    const char* slat_first   = grib_arguments_get_name(h,args,self->carg++);
    const char* slon_first   = grib_arguments_get_name(h,args,self->carg++);
    const char* slat_last    = grib_arguments_get_name(h,args,self->carg++);
    const char* slon_last    = grib_arguments_get_name(h,args,self->carg++);
    const char* sorder       = grib_arguments_get_name(h,args,self->carg++);
    const char* spl          = grib_arguments_get_name(h,args,self->carg++);
    const char* snj          = grib_arguments_get_name(h,args,self->carg++);

    if((ret = grib_get_double_internal(h, slat_first,&lat_first)) != GRIB_SUCCESS)
        return ret;
    if((ret = grib_get_double_internal(h, slon_first,&lon_first)) != GRIB_SUCCESS)
        return ret;
    if((ret = grib_get_double_internal(h, slat_last,&lat_last)) != GRIB_SUCCESS)
        return ret;
    if((ret = grib_get_double_internal(h, slon_last,&lon_last)) != GRIB_SUCCESS)
        return ret;

    if((ret = grib_get_long_internal(h, sorder,&order)) != GRIB_SUCCESS)
        return ret;
    if((ret = grib_get_long_internal(h, snj,&nj)) != GRIB_SUCCESS)
        return ret;

    if (grib_get_long(h, "editionNumber", &editionNumber)==GRIB_SUCCESS) {
        if (editionNumber == 1) angular_precision = 1.0/1000;
    }

    lats=(double*)grib_context_malloc(h->context,sizeof(double)*order*2);
    if (!lats) return GRIB_OUT_OF_MEMORY;
    if((ret = grib_get_gaussian_latitudes(order, lats)) != GRIB_SUCCESS)
        return ret;

    if((ret = grib_get_size(h,spl,&plsize)) != GRIB_SUCCESS)
        return ret;

    Assert(plsize);
    pl=(long*)grib_context_malloc(c,sizeof(long)*plsize);
    if (!pl) return GRIB_OUT_OF_MEMORY;

    grib_get_long_array_internal(h,spl,pl, &plsize);

    self->las = (double*)grib_context_malloc(h->context,iter->nv*sizeof(double));
    if (!self->las) return GRIB_OUT_OF_MEMORY;
    self->los = (double*)grib_context_malloc(h->context,iter->nv*sizeof(double));
    if (!self->los) return GRIB_OUT_OF_MEMORY;

    while (lon_last<0) lon_last+=360;
    while (lon_first<0) lon_first+=360;

    /* Find the maximum element of "pl" array, do not assume it's 4*N! */
    /* This could be an Octahedral Gaussian Grid */
    max_pl = pl[0];
    for (j=1; j<plsize; j++) {
        if (pl[j] > max_pl) max_pl = pl[j];
    }

    is_global = is_gaussian_global(lat_first, lat_last, lon_first, lon_last, max_pl, lats, angular_precision);
    if ( !is_global ) {
        int l=0;
        /*sub area*/
        /*find starting latitude */
        const double d = fabs(lats[0] - lats[1]);
        while (fabs(lat_first-lats[l]) > d ) {l++;}
        iter->e=0;
        for (j=0;j<plsize;j++) {
            row_count=0;
            grib_get_reduced_row(pl[j],lon_first,lon_last,
                    &row_count,&ilon_first,&ilon_last);
            if (ilon_first>ilon_last) ilon_first-=pl[j];
            for (i=ilon_first;i<=ilon_last;i++) {
#ifdef DEBUG
                Assert(iter->e < iter->nv);
#endif
                self->los[iter->e]=((i)*360.0)/pl[j];
                self->las[iter->e]=lats[j+l];
                iter->e++;
            }
        }
    } else {
        /*global*/
        iter->e=0;
        for (j=0;j<plsize;j++) {
            row_count=pl[j];
            for (i=0;i<row_count;i++) {
#ifdef DEBUG
                Assert(iter->e < iter->nv);
#endif
                self->los[iter->e]=(i*360.0)/row_count;
                self->las[iter->e]=lats[j];
                iter->e++;
            }
        }
    }

    iter->e = -1;
    grib_context_free(h->context,lats);
    grib_context_free(h->context,pl);

    return ret;
}