Beispiel #1
0
int codes_grib_iterator_reset(grib_iterator *i)
{
    return grib_iterator_reset(i);
}
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;
}