mirror of https://github.com/ecmwf/eccodes.git
Merge branch 'develop' into feature/LAEA_Oblate
This commit is contained in:
commit
fbdee2773a
|
@ -2,7 +2,7 @@
|
|||
# general configuration #
|
||||
#---------------------------------#
|
||||
|
||||
version: 2.18.0-{build}-{branch}
|
||||
version: 2.19.0-{build}-{branch}
|
||||
|
||||
branches:
|
||||
only:
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
cmake_minimum_required( VERSION 3.6 FATAL_ERROR )
|
||||
|
||||
project( eccodes VERSION 2.18.0 LANGUAGES C )
|
||||
project( eccodes VERSION 2.19.0 LANGUAGES C )
|
||||
|
||||
set( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../ecbuild/cmake" )
|
||||
|
||||
|
@ -119,7 +119,7 @@ ecbuild_add_option( FEATURE AEC
|
|||
|
||||
ecbuild_add_option( FEATURE PYTHON
|
||||
DESCRIPTION "Build the ecCodes Python2 interface (deprecated)"
|
||||
DEFAULT ON
|
||||
DEFAULT OFF
|
||||
REQUIRED_PACKAGES "Python VERSION 2.6 NO_LIBS" NumPy )
|
||||
# For Python2 we build our own bindings (using SWIG) in the build directory
|
||||
# but for Python3 one has to add the eccodes from pip3 AFTER the install
|
||||
|
|
|
@ -64,6 +64,8 @@ iterator mercator(numberOfPoints,missingValue,values,
|
|||
jPointsAreConsecutive,
|
||||
alternativeRowScanning);
|
||||
|
||||
nearest mercator(values,radius,Nx,Ny);
|
||||
|
||||
meta latLonValues latlonvalues(values);
|
||||
alias latitudeLongitudeValues=latLonValues;
|
||||
meta latitudes latitudes(values,0);
|
||||
|
|
|
@ -75,6 +75,8 @@ iterator mercator(numberOfPoints,missingValue,values,
|
|||
iScansNegatively, jScansPositively,
|
||||
jPointsAreConsecutive, alternativeRowScanning);
|
||||
|
||||
nearest mercator(values,radius,Nx,Ny);
|
||||
|
||||
meta latLonValues latlonvalues(values);
|
||||
alias latitudeLongitudeValues=latLonValues;
|
||||
meta latitudes latitudes(values,0);
|
||||
|
|
|
@ -60,6 +60,8 @@ iterator lambert_azimuthal_equal_area(numberOfPoints,missingValue,values,
|
|||
iScansNegatively, jScansPositively,
|
||||
jPointsAreConsecutive, alternativeRowScanning);
|
||||
|
||||
nearest lambert_azimuthal_equal_area(values,radius,Nx,Ny);
|
||||
|
||||
meta latLonValues latlonvalues(values);
|
||||
alias latitudeLongitudeValues=latLonValues;
|
||||
meta latitudes latitudes(values,0);
|
||||
|
|
|
@ -80,6 +80,8 @@ iterator space_view(numberOfPoints, missingValue, values, radius,
|
|||
iScansNegatively, jScansPositively,
|
||||
jPointsAreConsecutive, alternativeRowScanning);
|
||||
|
||||
nearest space_view(values,radius,Nx,Ny);
|
||||
|
||||
meta latLonValues latlonvalues(values);
|
||||
alias latitudeLongitudeValues=latLonValues;
|
||||
meta latitudes latitudes(values,0);
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
alias mars.anoffset=offsetToEndOf4DvarWindow;
|
||||
alias mars.number=componentIndex;
|
|
@ -0,0 +1 @@
|
|||
alias mars.number=componentIndex;
|
|
@ -346,7 +346,10 @@ list( APPEND grib_api_srcs
|
|||
grib_nearest_class_latlon_reduced.c
|
||||
grib_nearest_class_sh.c
|
||||
grib_nearest_class_lambert_conformal.c
|
||||
grib_nearest_class_lambert_azimuthal_equal_area.c
|
||||
grib_nearest_class_mercator.c
|
||||
grib_nearest_class_polar_stereographic.c
|
||||
grib_nearest_class_space_view.c
|
||||
grib_iterator_class_polar_stereographic.c
|
||||
grib_iterator_class_lambert_azimuthal_equal_area.c
|
||||
grib_iterator_class_lambert_conformal.c
|
||||
|
|
|
@ -361,7 +361,10 @@ libeccodes_la_prototypes= \
|
|||
grib_nearest_class_latlon_reduced.c \
|
||||
grib_nearest_class_sh.c \
|
||||
grib_nearest_class_lambert_conformal.c \
|
||||
grib_nearest_class_lambert_azimuthal_equal_area.c \
|
||||
grib_nearest_class_mercator.c \
|
||||
grib_nearest_class_polar_stereographic.c \
|
||||
grib_nearest_class_space_view.c \
|
||||
grib_iterator_class_polar_stereographic.c \
|
||||
grib_iterator_class_lambert_azimuthal_equal_area.c \
|
||||
grib_iterator_class_lambert_conformal.c \
|
||||
|
|
|
@ -1048,6 +1048,8 @@ int grib_get_gaussian_latitudes(long trunc, double* lats);
|
|||
int is_gaussian_global(double lat1, double lat2, double lon1, double lon2, long num_points_equator, const double* latitudes, double angular_precision);
|
||||
void rotate(const double inlat, const double inlon, const double angleOfRot, const double southPoleLat, const double southPoleLon, double* outlat, double* outlon);
|
||||
void unrotate(const double inlat, const double inlon, const double angleOfRot, const double southPoleLat, const double southPoleLon, double* outlat, double* outlon);
|
||||
double geographic_distance_spherical(double radius, double lon1, double lat1, double lon2, double lat2);
|
||||
double geographic_distance_ellipsoid(double major, double minor, double lon1, double lat1, double lon2, double lat2);
|
||||
|
||||
/* grib_handle.c */
|
||||
grib_section* grib_section_create(grib_handle* h, grib_accessor* owner);
|
||||
|
@ -1376,8 +1378,16 @@ int grib_nearest_find(grib_nearest* nearest, const grib_handle* h, double inlat,
|
|||
int grib_nearest_init(grib_nearest* i, grib_handle* h, grib_arguments* args);
|
||||
int grib_nearest_delete(grib_nearest* i);
|
||||
void grib_binary_search(double xx[], const unsigned long n, double x, int* ju, int* jl);
|
||||
double grib_nearest_distance(double radius, double lon1, double lat1, double lon2, double lat2);
|
||||
int grib_nearest_find_multiple(const grib_handle* h, int is_lsm, const double* inlats, const double* inlons, long npoints, double* outlats, double* outlons, double* values, double* distances, int* indexes);
|
||||
int grib_nearest_find_generic(grib_nearest* nearest, grib_handle* h, double inlat, double inlon, unsigned long flags,
|
||||
const char* values_keyname, const char* radius_keyname,
|
||||
const char* Ni_keyname, const char* Nj_keyname,
|
||||
double** out_lats,
|
||||
int* out_lats_count,
|
||||
double** out_lons,
|
||||
int* out_lons_count,
|
||||
double** out_distances,
|
||||
double* outlats, double* outlons, double* values, double* distances, int* indexes, size_t* len);
|
||||
|
||||
/* grib_nearest_class.c */
|
||||
grib_nearest* grib_nearest_factory(grib_handle* h, grib_arguments* args);
|
||||
|
|
|
@ -420,7 +420,7 @@ int grib_encode_size_tb(unsigned char* p, size_t val, long* bitp, long nb)
|
|||
#if OMP_PACKING
|
||||
#include "grib_bits_any_endian_omp.c"
|
||||
#elif VECTOR
|
||||
#include "grib_bits_any_endian_vector.c"
|
||||
#include "grib_bits_any_endian_vector.c" /* Experimental */
|
||||
#else
|
||||
#include "grib_bits_any_endian_simple.c"
|
||||
#endif
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
/***************************************************************************
|
||||
* Enrico Fucile - 19.06.2007 *
|
||||
* *
|
||||
* EXPERIMENTAL CODE - NOT FULLY TESTED *
|
||||
***************************************************************************/
|
||||
|
||||
int grib_decode_long_array(const unsigned char* p, long* bitp, long bitsPerValue,
|
||||
|
@ -19,7 +19,8 @@ int grib_decode_long_array(const unsigned char* p, long* bitp, long bitsPerValue
|
|||
long i = 0;
|
||||
unsigned long lvalue = 0;
|
||||
|
||||
if (bitsPerValue % 8) {
|
||||
/* SUP-3196: Thanks to Daniel Tameling */
|
||||
if (bitsPerValue % 8 || (*bitp & 7)) {
|
||||
int j = 0;
|
||||
for (i = 0; i < n_vals; i++) {
|
||||
lvalue = 0;
|
||||
|
@ -54,7 +55,6 @@ int grib_decode_long_array(const unsigned char* p, long* bitp, long bitsPerValue
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int grib_decode_double_array(const unsigned char* p, long* bitp, long bitsPerValue,
|
||||
double reference_value, double s, double d,
|
||||
size_t n_vals, double* val)
|
||||
|
@ -96,12 +96,14 @@ int grib_decode_double_array(const unsigned char* p, long* bitp, long bitsPerVal
|
|||
return 0;
|
||||
}
|
||||
|
||||
int grib_decode_double_array_complex(const unsigned char* p, long* bitp, long nbits, double reference_value, double s, double* d, size_t size, double* val)
|
||||
int grib_decode_double_array_complex(const unsigned char* p, long* bitp, long nbits, double reference_value,
|
||||
double s, double* d, size_t size, double* val)
|
||||
{
|
||||
return GRIB_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
int grib_encode_double_array(size_t n_vals, const double* val, long bits_per_value, double reference_value, double d, double divisor, unsigned char* p, long* off)
|
||||
int grib_encode_double_array(size_t n_vals, const double* val, long bits_per_value, double reference_value,
|
||||
double d, double divisor, unsigned char* p, long* off)
|
||||
{
|
||||
size_t i = 0;
|
||||
unsigned long unsigned_val = 0;
|
||||
|
|
|
@ -186,7 +186,7 @@ int grib_encode_unsigned_longb(unsigned char* p, unsigned long val, long* bitp,
|
|||
}
|
||||
|
||||
#if VECTOR
|
||||
#include "grib_bits_fast_big_endian_vector.c"
|
||||
#include "grib_bits_fast_big_endian_vector.c" /* Experimental */
|
||||
#elif OMP
|
||||
#include "grib_bits_fast_big_endian_omp.c"
|
||||
#else
|
||||
|
|
|
@ -4140,3 +4140,73 @@ void unrotate(const double inlat, const double inlon,
|
|||
*outlat = ret_lat;
|
||||
*outlon = ret_lon;
|
||||
}
|
||||
|
||||
#define RADIAN(x) ((x)*acos(0.0) / 90.0)
|
||||
|
||||
/* radius is in km, angles in degrees */
|
||||
/* Spherical Law of Cosines */
|
||||
double geographic_distance_spherical(double radius, double lon1, double lat1, double lon2, double lat2)
|
||||
{
|
||||
double rlat1 = RADIAN(lat1);
|
||||
double rlat2 = RADIAN(lat2);
|
||||
double rlon1 = lon1;
|
||||
double rlon2 = lon2;
|
||||
double a;
|
||||
|
||||
if (lat1 == lat2 && lon1 == lon2) {
|
||||
return 0.0; /* the two points are identical */
|
||||
}
|
||||
|
||||
if (rlon1 >= 360) rlon1 -= 360.0;
|
||||
rlon1 = RADIAN(rlon1);
|
||||
if (rlon2 >= 360) rlon2 -= 360.0;
|
||||
rlon2 = RADIAN(rlon2);
|
||||
|
||||
a = sin(rlat1) * sin(rlat2) + cos(rlat1) * cos(rlat2) * cos(rlon2 - rlon1);
|
||||
DebugAssert(a >= -1 && a <= 1);
|
||||
|
||||
return radius * acos(a);
|
||||
}
|
||||
|
||||
/* major and minor axes in km, angles in degrees */
|
||||
double geographic_distance_ellipsoid(double major, double minor, double lon1, double lat1, double lon2, double lat2)
|
||||
{
|
||||
/* Lambert's formula */
|
||||
double rlat1 = RADIAN(lat1);
|
||||
double rlat2 = RADIAN(lat2);
|
||||
double rlon1 = RADIAN(lon1);
|
||||
double rlon2 = RADIAN(lon2);
|
||||
double deltaLat = rlat2 - rlat1;
|
||||
double deltaLon = rlon2 - rlon1;
|
||||
double sinDlat = sin(deltaLat/2.0);
|
||||
double sinDlon = sin(deltaLon/2.0);
|
||||
double sin2Dlat = sinDlat*sinDlat;
|
||||
double sin2Dlon = sinDlon*sinDlon;
|
||||
|
||||
double a = sin2Dlat + cos(rlat1) * cos(rlat2) * sin2Dlon;
|
||||
double c = 2 * atan2(sqrt(a), sqrt(1.0-a));
|
||||
double f = (major - minor)/major; /*flattening*/
|
||||
|
||||
double latr1 = atan( (1.0-f)*tan(rlat1) ); /*Reduced latitude1*/
|
||||
double latr2 = atan( (1.0-f)*tan(rlat2) ); /*Reduced latitude2*/
|
||||
double P = (latr1+latr2)/2;
|
||||
double Q = (latr2-latr1)/2;
|
||||
double sinP = sin(P);
|
||||
double sin2P = sinP*sinP;
|
||||
double cosQ = cos(Q);
|
||||
double cos2Q = cosQ*cosQ;
|
||||
double cosc2 = cos(c/2);
|
||||
double cos2c2 = cosc2*cosc2;
|
||||
|
||||
double sinQ = sin(Q);
|
||||
double sin2Q = sinQ*sinQ;
|
||||
double cosP = cos(P);
|
||||
double cos2P = cosP*cosP;
|
||||
double sinc2 = sin(c/2);
|
||||
double sin2c2 = sinc2*sinc2;
|
||||
|
||||
double X = (c - sin(c))* sin2P * cos2Q / cos2c2;
|
||||
double Y = (c + sin(c))*sin2Q*cos2P/sin2c2;
|
||||
double dist = major * (c - f*(X+Y)/2);
|
||||
return dist;
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ static int read_the_rest(reader* r, size_t message_length, unsigned char* tmp, i
|
|||
size_t buffer_size;
|
||||
size_t rest;
|
||||
unsigned char* buffer;
|
||||
grib_context* c = grib_context_get_default();
|
||||
|
||||
if (message_length == 0)
|
||||
return GRIB_BUFFER_TOO_SMALL;
|
||||
|
@ -109,12 +110,20 @@ static int read_the_rest(reader* r, size_t message_length, unsigned char* tmp, i
|
|||
|
||||
if ((r->read(r->read_data, buffer + already_read, rest, &err) != rest) || err) {
|
||||
/*fprintf(stderr, "read_the_rest: r->read failed: %s\n", grib_get_error_message(err));*/
|
||||
if (c->debug)
|
||||
fprintf(stderr, "ECCODES DEBUG: read_the_rest: Read failed (Coded length=%lu, Already read=%d)\n",
|
||||
message_length, already_read);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (check7777 && !r->headers_only && (buffer[message_length - 4] != '7' || buffer[message_length - 3] != '7' || buffer[message_length - 2] != '7' || buffer[message_length - 1] != '7')) {
|
||||
grib_context* c = grib_context_get_default();
|
||||
grib_context_log(c, GRIB_LOG_DEBUG, "read_the_rest: No final 7777 at expected location (Coded length=%lu)", message_length);
|
||||
if (check7777 && !r->headers_only &&
|
||||
(buffer[message_length - 4] != '7' ||
|
||||
buffer[message_length - 3] != '7' ||
|
||||
buffer[message_length - 2] != '7' ||
|
||||
buffer[message_length - 1] != '7'))
|
||||
{
|
||||
if (c->debug)
|
||||
fprintf(stderr, "ECCODES DEBUG: read_the_rest: No final 7777 at expected location (Coded length=%lu)\n", message_length);
|
||||
return GRIB_WRONG_LENGTH;
|
||||
}
|
||||
|
||||
|
|
|
@ -360,9 +360,11 @@ static int init_oblate(grib_handle* h,
|
|||
latRad = -M_PI_2;
|
||||
}
|
||||
lonRad = adjust_lon_radians(theta / ns + LoVInRadians);
|
||||
if (i == 0 && j == 0) {
|
||||
DebugAssert(fabs(latFirstInRadians - latRad) <= EPSILON);
|
||||
}
|
||||
latDeg = latRad * RAD2DEG; /* Convert to degrees */
|
||||
lonDeg = lonRad * RAD2DEG;
|
||||
lonDeg = normalise_longitude_in_degrees(lonDeg);
|
||||
lonDeg = normalise_longitude_in_degrees(lonRad * RAD2DEG);
|
||||
self->lons[index] = lonDeg;
|
||||
self->lats[index] = latDeg;
|
||||
}
|
||||
|
|
|
@ -215,10 +215,12 @@ static int init_mercator(grib_handle* h,
|
|||
grib_context_free(h->context, self->lons);
|
||||
return err;
|
||||
}
|
||||
lonRad = adjust_lon_radians(orientationInRadians + _x / (earthMajorAxisInMetres * m1));
|
||||
lonRad = adjust_lon_radians(orientationInRadians + _x / (earthMajorAxisInMetres * m1));
|
||||
if (i == 0 && j == 0) {
|
||||
DebugAssert(fabs(latFirstInRadians - latRad) <= EPSILON);
|
||||
}
|
||||
latDeg = latRad * RAD2DEG; /* Convert to degrees */
|
||||
lonDeg = lonRad * RAD2DEG;
|
||||
lonDeg = normalise_longitude_in_degrees(lonDeg);
|
||||
lonDeg = normalise_longitude_in_degrees(lonRad * RAD2DEG);
|
||||
self->lons[index] = lonDeg;
|
||||
self->lats[index] = latDeg;
|
||||
}
|
||||
|
|
|
@ -114,35 +114,6 @@ void grib_binary_search(double xx[], const unsigned long n, double x,
|
|||
}
|
||||
}
|
||||
|
||||
#define RADIAN(x) ((x)*acos(0.0) / 90.0)
|
||||
|
||||
double grib_nearest_distance(double radius, double lon1, double lat1, double lon2, double lat2)
|
||||
{
|
||||
double rlat1 = RADIAN(lat1);
|
||||
double rlat2 = RADIAN(lat2);
|
||||
double rlon1 = lon1;
|
||||
double rlon2 = lon2;
|
||||
double a;
|
||||
|
||||
if (lat1 == lat2 && lon1 == lon2) {
|
||||
return 0.0; /* the two points are identical */
|
||||
}
|
||||
|
||||
if (rlon1 >= 360)
|
||||
rlon1 -= 360.0;
|
||||
rlon1 = RADIAN(rlon1);
|
||||
if (rlon2 >= 360)
|
||||
rlon2 -= 360.0;
|
||||
rlon2 = RADIAN(rlon2);
|
||||
|
||||
a = sin(rlat1) * sin(rlat2) + cos(rlat1) * cos(rlat2) * cos(rlon2 - rlon1);
|
||||
|
||||
if (a > 1 || a < -1)
|
||||
a = (int)a;
|
||||
|
||||
return radius * acos(a);
|
||||
}
|
||||
|
||||
int grib_nearest_find_multiple(
|
||||
const grib_handle* h, int is_lsm,
|
||||
const double* inlats, const double* inlons, long npoints,
|
||||
|
@ -241,3 +212,221 @@ int grib_nearest_find_multiple(
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Generic implementation of nearest for Lambert, Polar stereo, Mercator etc */
|
||||
static int compare_doubles(const void* a, const void* b, int ascending)
|
||||
{
|
||||
/* ascending is a boolean: 0 or 1 */
|
||||
double* arg1 = (double*)a;
|
||||
double* arg2 = (double*)b;
|
||||
if (ascending) {
|
||||
if (*arg1 < *arg2)
|
||||
return -1; /*Smaller values come before larger ones*/
|
||||
}
|
||||
else {
|
||||
if (*arg1 > *arg2)
|
||||
return -1; /*Larger values come before smaller ones*/
|
||||
}
|
||||
if (*arg1 == *arg2)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int compare_doubles_ascending(const void* a, const void* b)
|
||||
{
|
||||
return compare_doubles(a, b, 1);
|
||||
}
|
||||
|
||||
typedef struct PointStore
|
||||
{
|
||||
double m_lat;
|
||||
double m_lon;
|
||||
double m_dist;
|
||||
double m_value;
|
||||
int m_index;
|
||||
} PointStore;
|
||||
|
||||
/* Comparison function to sort points by distance */
|
||||
static int compare_points(const void* a, const void* b)
|
||||
{
|
||||
PointStore* pA = (PointStore*)a;
|
||||
PointStore* pB = (PointStore*)b;
|
||||
|
||||
if (pA->m_dist < pB->m_dist) return -1;
|
||||
if (pA->m_dist > pB->m_dist) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int grib_nearest_find_generic(
|
||||
grib_nearest* nearest, grib_handle* h,
|
||||
double inlat, double inlon, unsigned long flags,
|
||||
|
||||
const char* values_keyname,
|
||||
const char* radius_keyname,
|
||||
const char* Ni_keyname,
|
||||
const char* Nj_keyname,
|
||||
double** out_lats,
|
||||
int* out_lats_count,
|
||||
double** out_lons,
|
||||
int* out_lons_count,
|
||||
double** out_distances,
|
||||
|
||||
double* outlats, double* outlons,
|
||||
double* values, double* distances, int* indexes, size_t* len)
|
||||
{
|
||||
int ret = 0, i = 0;
|
||||
size_t nvalues = 0, nneighbours = 0;
|
||||
double radiusInMetres, radiusInKm;
|
||||
grib_iterator* iter = NULL;
|
||||
double lat = 0, lon = 0;
|
||||
|
||||
/* array of candidates for nearest neighbours */
|
||||
PointStore* neighbours = NULL;
|
||||
|
||||
inlon = normalise_longitude_in_degrees(inlon);
|
||||
|
||||
if ((ret = grib_get_size(h, values_keyname, &nvalues)) != GRIB_SUCCESS)
|
||||
return ret;
|
||||
nearest->values_count = nvalues;
|
||||
|
||||
/* We need the radius to calculate the nearest distance. For an oblate earth
|
||||
approximate this using the average of the semimajor and semiminor axes */
|
||||
if ((ret = grib_get_double(h, radius_keyname, &radiusInMetres)) == GRIB_SUCCESS &&
|
||||
!grib_is_missing(h, radius_keyname, &ret)) {
|
||||
radiusInKm = radiusInMetres / 1000.0;
|
||||
}
|
||||
else {
|
||||
double minor = 0, major = 0;
|
||||
if ((ret = grib_get_double_internal(h, "earthMinorAxisInMetres", &minor)) != GRIB_SUCCESS) return ret;
|
||||
if ((ret = grib_get_double_internal(h, "earthMajorAxisInMetres", &major)) != GRIB_SUCCESS) return ret;
|
||||
if (grib_is_missing(h, "earthMinorAxisInMetres", &ret)) return GRIB_GEOCALCULUS_PROBLEM;
|
||||
if (grib_is_missing(h, "earthMajorAxisInMetres", &ret)) return GRIB_GEOCALCULUS_PROBLEM;
|
||||
radiusInMetres = (major + minor) / 2;
|
||||
radiusInKm = radiusInMetres / 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 */
|
||||
const double LAT_DELTA = 10.0; /* in degrees */
|
||||
|
||||
if (grib_is_missing(h, Ni_keyname, &ret)) {
|
||||
grib_context_log(h->context, GRIB_LOG_DEBUG, "Key '%s' is missing", Ni_keyname);
|
||||
return ret ? ret : GRIB_GEOCALCULUS_PROBLEM;
|
||||
}
|
||||
|
||||
if (grib_is_missing(h, Nj_keyname, &ret)) {
|
||||
grib_context_log(h->context, GRIB_LOG_DEBUG, "Key '%s' is missing", Nj_keyname);
|
||||
return ret ? ret : GRIB_GEOCALCULUS_PROBLEM;
|
||||
}
|
||||
|
||||
*out_lons_count = nvalues; /* Maybe overestimate but safe */
|
||||
*out_lats_count = nvalues;
|
||||
|
||||
if (*out_lats)
|
||||
grib_context_free(nearest->context, *out_lats);
|
||||
*out_lats = (double*)grib_context_malloc(nearest->context, nvalues * sizeof(double));
|
||||
if (!*out_lats)
|
||||
return GRIB_OUT_OF_MEMORY;
|
||||
|
||||
if (*out_lons)
|
||||
grib_context_free(nearest->context, *out_lons);
|
||||
*out_lons = (double*)grib_context_malloc(nearest->context, nvalues * sizeof(double));
|
||||
if (!*out_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 < *out_lats_count);
|
||||
Assert(ilon < *out_lons_count);
|
||||
(*out_lats)[ilat++] = lat;
|
||||
(*out_lons)[ilon++] = lon;
|
||||
}
|
||||
|
||||
/* See between which 2 latitudes our point lies */
|
||||
qsort(*out_lats, nvalues, sizeof(double), &compare_doubles_ascending);
|
||||
grib_binary_search(*out_lats, *out_lats_count - 1, inlat, &idx_upper, &idx_lower);
|
||||
lat2 = (*out_lats)[idx_upper];
|
||||
lat1 = (*out_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 {
|
||||
double dist = geographic_distance_spherical(radiusInKm, 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;
|
||||
}
|
||||
nneighbours = i;
|
||||
/* Sort the candidate neighbours in ascending order of distance */
|
||||
/* The first 4 entries will now be the closest 4 neighbours */
|
||||
qsort(neighbours, nneighbours, sizeof(PointStore), &compare_points);
|
||||
|
||||
grib_iterator_delete(iter);
|
||||
}
|
||||
nearest->h = h;
|
||||
|
||||
/* Sanity check for sorting */
|
||||
#ifdef DEBUG
|
||||
for (i = 0; i < nneighbours - 1; ++i) {
|
||||
Assert(neighbours[i].m_dist <= neighbours[i + 1].m_dist);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* GRIB_NEAREST_SAME_XXX not yet implemented */
|
||||
if (!*out_distances) {
|
||||
*out_distances = (double*)grib_context_malloc(nearest->context, 4 * sizeof(double));
|
||||
}
|
||||
(*out_distances)[0] = neighbours[0].m_dist;
|
||||
(*out_distances)[1] = neighbours[1].m_dist;
|
||||
(*out_distances)[2] = neighbours[2].m_dist;
|
||||
(*out_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;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
/* This file is automatically generated by ./make_class.pl, do not edit */
|
||||
extern grib_nearest_class* grib_nearest_class_gen;
|
||||
extern grib_nearest_class* grib_nearest_class_lambert_azimuthal_equal_area;
|
||||
extern grib_nearest_class* grib_nearest_class_lambert_conformal;
|
||||
extern grib_nearest_class* grib_nearest_class_latlon_reduced;
|
||||
extern grib_nearest_class* grib_nearest_class_mercator;
|
||||
extern grib_nearest_class* grib_nearest_class_polar_stereographic;
|
||||
extern grib_nearest_class* grib_nearest_class_reduced;
|
||||
extern grib_nearest_class* grib_nearest_class_regular;
|
||||
extern grib_nearest_class* grib_nearest_class_sh;
|
||||
extern grib_nearest_class* grib_nearest_class_space_view;
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* (C) Copyright 2005- ECMWF.
|
||||
*
|
||||
* This software is licensed under the terms of the Apache Licence Version 2.0
|
||||
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
|
||||
* virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
|
||||
*/
|
||||
|
||||
#include "grib_api_internal.h"
|
||||
|
||||
/*
|
||||
This is used by make_class.pl
|
||||
|
||||
START_CLASS_DEF
|
||||
CLASS = nearest
|
||||
SUPER = grib_nearest_class_gen
|
||||
IMPLEMENTS = init
|
||||
IMPLEMENTS = find;destroy
|
||||
MEMBERS = double* lats
|
||||
MEMBERS = int lats_count
|
||||
MEMBERS = double* lons
|
||||
MEMBERS = int lons_count
|
||||
MEMBERS = double* distances
|
||||
MEMBERS = int* k
|
||||
MEMBERS = int* i
|
||||
MEMBERS = int* j
|
||||
MEMBERS = const char* Ni
|
||||
MEMBERS = const char* Nj
|
||||
END_CLASS_DEF
|
||||
|
||||
*/
|
||||
|
||||
/* START_CLASS_IMP */
|
||||
|
||||
/*
|
||||
|
||||
Don't edit anything between START_CLASS_IMP and END_CLASS_IMP
|
||||
Instead edit values between START_CLASS_DEF and END_CLASS_DEF
|
||||
or edit "nearest.class" and rerun ./make_class.pl
|
||||
|
||||
*/
|
||||
|
||||
|
||||
static void init_class(grib_nearest_class*);
|
||||
|
||||
static int init(grib_nearest* nearest, grib_handle* h, grib_arguments* args);
|
||||
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);
|
||||
static int destroy(grib_nearest* nearest);
|
||||
|
||||
typedef struct grib_nearest_lambert_azimuthal_equal_area
|
||||
{
|
||||
grib_nearest nearest;
|
||||
/* Members defined in gen */
|
||||
const char* values_key;
|
||||
const char* radius;
|
||||
int cargs;
|
||||
/* Members defined in lambert_azimuthal_equal_area */
|
||||
double* lats;
|
||||
int lats_count;
|
||||
double* lons;
|
||||
int lons_count;
|
||||
double* distances;
|
||||
int* k;
|
||||
int* i;
|
||||
int* j;
|
||||
const char* Ni;
|
||||
const char* Nj;
|
||||
} grib_nearest_lambert_azimuthal_equal_area;
|
||||
|
||||
extern grib_nearest_class* grib_nearest_class_gen;
|
||||
|
||||
static grib_nearest_class _grib_nearest_class_lambert_azimuthal_equal_area = {
|
||||
&grib_nearest_class_gen, /* super */
|
||||
"lambert_azimuthal_equal_area", /* name */
|
||||
sizeof(grib_nearest_lambert_azimuthal_equal_area), /* size of instance */
|
||||
0, /* inited */
|
||||
&init_class, /* init_class */
|
||||
&init, /* constructor */
|
||||
&destroy, /* destructor */
|
||||
&find, /* find nearest */
|
||||
};
|
||||
|
||||
grib_nearest_class* grib_nearest_class_lambert_azimuthal_equal_area = &_grib_nearest_class_lambert_azimuthal_equal_area;
|
||||
|
||||
|
||||
static void init_class(grib_nearest_class* c)
|
||||
{
|
||||
}
|
||||
/* END_CLASS_IMP */
|
||||
|
||||
static int init(grib_nearest* nearest, grib_handle* h, grib_arguments* args)
|
||||
{
|
||||
grib_nearest_lambert_azimuthal_equal_area* self = (grib_nearest_lambert_azimuthal_equal_area*)nearest;
|
||||
self->Ni = grib_arguments_get_name(h, args, self->cargs++);
|
||||
self->Nj = grib_arguments_get_name(h, args, self->cargs++);
|
||||
self->i = (int*)grib_context_malloc(h->context, 2 * sizeof(int));
|
||||
self->j = (int*)grib_context_malloc(h->context, 2 * sizeof(int));
|
||||
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_azimuthal_equal_area* self = (grib_nearest_lambert_azimuthal_equal_area*)nearest;
|
||||
return grib_nearest_find_generic(
|
||||
nearest, h, inlat, inlon, flags, /* inputs */
|
||||
|
||||
self->values_key, /* outputs to set the 'self' object */
|
||||
self->radius,
|
||||
self->Ni,
|
||||
self->Nj,
|
||||
&(self->lats),
|
||||
&(self->lats_count),
|
||||
&(self->lons),
|
||||
&(self->lons_count),
|
||||
&(self->distances),
|
||||
|
||||
outlats, outlons, /* outputs of the find function */
|
||||
values, distances, indexes, len);
|
||||
}
|
||||
|
||||
static int destroy(grib_nearest* nearest)
|
||||
{
|
||||
grib_nearest_lambert_azimuthal_equal_area* self = (grib_nearest_lambert_azimuthal_equal_area*)nearest;
|
||||
if (self->lats) grib_context_free(nearest->context, self->lats);
|
||||
if (self->lons) grib_context_free(nearest->context, self->lons);
|
||||
if (self->i) grib_context_free(nearest->context, self->i);
|
||||
if (self->j) grib_context_free(nearest->context, self->j);
|
||||
if (self->k) grib_context_free(nearest->context, self->k);
|
||||
if (self->distances) grib_context_free(nearest->context, self->distances);
|
||||
return GRIB_SUCCESS;
|
||||
}
|
|
@ -100,224 +100,37 @@ static int init(grib_nearest* nearest, grib_handle* h, grib_arguments* args)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int compare_doubles(const void* a, const void* b, int ascending)
|
||||
{
|
||||
/* ascending is a boolean: 0 or 1 */
|
||||
double* arg1 = (double*)a;
|
||||
double* arg2 = (double*)b;
|
||||
if (ascending) {
|
||||
if (*arg1 < *arg2)
|
||||
return -1; /*Smaller values come before larger ones*/
|
||||
}
|
||||
else {
|
||||
if (*arg1 > *arg2)
|
||||
return -1; /*Larger values come before smaller ones*/
|
||||
}
|
||||
if (*arg1 == *arg2)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int compare_doubles_ascending(const void* a, const void* b)
|
||||
{
|
||||
return compare_doubles(a, b, 1);
|
||||
}
|
||||
|
||||
typedef struct PointStore
|
||||
{
|
||||
double m_lat;
|
||||
double m_lon;
|
||||
double m_dist;
|
||||
double m_value;
|
||||
int m_index;
|
||||
} PointStore;
|
||||
|
||||
/* Comparison function to sort points by distance */
|
||||
static int compare_points(const void* a, const void* b)
|
||||
{
|
||||
PointStore* pA = (PointStore*)a;
|
||||
PointStore* pB = (PointStore*)b;
|
||||
|
||||
if (pA->m_dist < pB->m_dist)
|
||||
return -1;
|
||||
if (pA->m_dist > pB->m_dist)
|
||||
return 1;
|
||||
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;
|
||||
return grib_nearest_find_generic(
|
||||
nearest, h, inlat, inlon, flags, /* inputs */
|
||||
|
||||
/* array of candidates for nearest neighbours */
|
||||
PointStore* neighbours = NULL;
|
||||
self->values_key, /* outputs to set the 'self' object */
|
||||
self->radius,
|
||||
self->Ni,
|
||||
self->Nj,
|
||||
&(self->lats),
|
||||
&(self->lats_count),
|
||||
&(self->lons),
|
||||
&(self->lons_count),
|
||||
&(self->distances),
|
||||
|
||||
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;
|
||||
outlats, outlons, /* outputs of the find function */
|
||||
values, distances, indexes, len);
|
||||
}
|
||||
|
||||
static int destroy(grib_nearest* nearest)
|
||||
{
|
||||
grib_nearest_lambert_conformal* self = (grib_nearest_lambert_conformal*)nearest;
|
||||
if (self->lats)
|
||||
grib_context_free(nearest->context, self->lats);
|
||||
if (self->lons)
|
||||
grib_context_free(nearest->context, self->lons);
|
||||
if (self->i)
|
||||
grib_context_free(nearest->context, self->i);
|
||||
if (self->j)
|
||||
grib_context_free(nearest->context, self->j);
|
||||
if (self->k)
|
||||
grib_context_free(nearest->context, self->k);
|
||||
if (self->distances)
|
||||
grib_context_free(nearest->context, self->distances);
|
||||
if (self->lats) grib_context_free(nearest->context, self->lats);
|
||||
if (self->lons) grib_context_free(nearest->context, self->lons);
|
||||
if (self->i) grib_context_free(nearest->context, self->i);
|
||||
if (self->j) grib_context_free(nearest->context, self->j);
|
||||
if (self->k) grib_context_free(nearest->context, self->k);
|
||||
if (self->distances) grib_context_free(nearest->context, self->distances);
|
||||
return GRIB_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -346,7 +346,7 @@ static int find(grib_nearest* nearest, grib_handle* h,
|
|||
kk = 0;
|
||||
for (jj = 0; jj < 2; jj++) {
|
||||
for (ii = 0; ii < 2; ii++) {
|
||||
self->distances[kk] = grib_nearest_distance(radius, inlon, inlat,
|
||||
self->distances[kk] = geographic_distance_spherical(radius, inlon, inlat,
|
||||
self->lons[self->k[kk]], self->lats[self->j[jj]]);
|
||||
kk++;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* (C) Copyright 2005- ECMWF.
|
||||
*
|
||||
* This software is licensed under the terms of the Apache Licence Version 2.0
|
||||
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
|
||||
* virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
|
||||
*/
|
||||
|
||||
#include "grib_api_internal.h"
|
||||
|
||||
/*
|
||||
This is used by make_class.pl
|
||||
|
||||
START_CLASS_DEF
|
||||
CLASS = nearest
|
||||
SUPER = grib_nearest_class_gen
|
||||
IMPLEMENTS = init
|
||||
IMPLEMENTS = find;destroy
|
||||
MEMBERS = double* lats
|
||||
MEMBERS = int lats_count
|
||||
MEMBERS = double* lons
|
||||
MEMBERS = int lons_count
|
||||
MEMBERS = double* distances
|
||||
MEMBERS = int* k
|
||||
MEMBERS = int* i
|
||||
MEMBERS = int* j
|
||||
MEMBERS = const char* Ni
|
||||
MEMBERS = const char* Nj
|
||||
END_CLASS_DEF
|
||||
|
||||
*/
|
||||
|
||||
/* START_CLASS_IMP */
|
||||
|
||||
/*
|
||||
|
||||
Don't edit anything between START_CLASS_IMP and END_CLASS_IMP
|
||||
Instead edit values between START_CLASS_DEF and END_CLASS_DEF
|
||||
or edit "nearest.class" and rerun ./make_class.pl
|
||||
|
||||
*/
|
||||
|
||||
|
||||
static void init_class(grib_nearest_class*);
|
||||
|
||||
static int init(grib_nearest* nearest, grib_handle* h, grib_arguments* args);
|
||||
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);
|
||||
static int destroy(grib_nearest* nearest);
|
||||
|
||||
typedef struct grib_nearest_mercator
|
||||
{
|
||||
grib_nearest nearest;
|
||||
/* Members defined in gen */
|
||||
const char* values_key;
|
||||
const char* radius;
|
||||
int cargs;
|
||||
/* Members defined in mercator */
|
||||
double* lats;
|
||||
int lats_count;
|
||||
double* lons;
|
||||
int lons_count;
|
||||
double* distances;
|
||||
int* k;
|
||||
int* i;
|
||||
int* j;
|
||||
const char* Ni;
|
||||
const char* Nj;
|
||||
} grib_nearest_mercator;
|
||||
|
||||
extern grib_nearest_class* grib_nearest_class_gen;
|
||||
|
||||
static grib_nearest_class _grib_nearest_class_mercator = {
|
||||
&grib_nearest_class_gen, /* super */
|
||||
"mercator", /* name */
|
||||
sizeof(grib_nearest_mercator), /* size of instance */
|
||||
0, /* inited */
|
||||
&init_class, /* init_class */
|
||||
&init, /* constructor */
|
||||
&destroy, /* destructor */
|
||||
&find, /* find nearest */
|
||||
};
|
||||
|
||||
grib_nearest_class* grib_nearest_class_mercator = &_grib_nearest_class_mercator;
|
||||
|
||||
|
||||
static void init_class(grib_nearest_class* c)
|
||||
{
|
||||
}
|
||||
/* END_CLASS_IMP */
|
||||
|
||||
static int init(grib_nearest* nearest, grib_handle* h, grib_arguments* args)
|
||||
{
|
||||
grib_nearest_mercator* self = (grib_nearest_mercator*)nearest;
|
||||
self->Ni = grib_arguments_get_name(h, args, self->cargs++);
|
||||
self->Nj = grib_arguments_get_name(h, args, self->cargs++);
|
||||
self->lats = self->lons = self->distances = NULL;
|
||||
self->lats_count = self->lons_count = 0;
|
||||
self->i = (int*)grib_context_malloc(h->context, 2 * sizeof(int));
|
||||
self->j = (int*)grib_context_malloc(h->context, 2 * sizeof(int));
|
||||
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_mercator* self = (grib_nearest_mercator*)nearest;
|
||||
return grib_nearest_find_generic(
|
||||
nearest, h, inlat, inlon, flags, /* inputs */
|
||||
|
||||
self->values_key, /* outputs to set the 'self' object */
|
||||
self->radius,
|
||||
self->Ni,
|
||||
self->Nj,
|
||||
&(self->lats),
|
||||
&(self->lats_count),
|
||||
&(self->lons),
|
||||
&(self->lons_count),
|
||||
&(self->distances),
|
||||
|
||||
outlats, outlons, /* outputs of the find function */
|
||||
values, distances, indexes, len);
|
||||
}
|
||||
|
||||
static int destroy(grib_nearest* nearest)
|
||||
{
|
||||
grib_nearest_mercator* self = (grib_nearest_mercator*)nearest;
|
||||
if (self->lats) grib_context_free(nearest->context, self->lats);
|
||||
if (self->lons) grib_context_free(nearest->context, self->lons);
|
||||
if (self->i) grib_context_free(nearest->context, self->i);
|
||||
if (self->j) grib_context_free(nearest->context, self->j);
|
||||
if (self->k) grib_context_free(nearest->context, self->k);
|
||||
if (self->distances) grib_context_free(nearest->context, self->distances);
|
||||
return GRIB_SUCCESS;
|
||||
}
|
|
@ -97,53 +97,7 @@ static int init(grib_nearest* nearest, grib_handle* h, grib_arguments* args)
|
|||
self->Nj = grib_arguments_get_name(h, args, self->cargs++);
|
||||
self->i = (int*)grib_context_malloc(h->context, 2 * sizeof(int));
|
||||
self->j = (int*)grib_context_malloc(h->context, 2 * sizeof(int));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compare_doubles(const void* a, const void* b, int ascending)
|
||||
{
|
||||
/* ascending is a boolean: 0 or 1 */
|
||||
double* arg1 = (double*)a;
|
||||
double* arg2 = (double*)b;
|
||||
if (ascending) {
|
||||
if (*arg1 < *arg2)
|
||||
return -1; /*Smaller values come before larger ones*/
|
||||
}
|
||||
else {
|
||||
if (*arg1 > *arg2)
|
||||
return -1; /*Larger values come before smaller ones*/
|
||||
}
|
||||
if (*arg1 == *arg2)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int compare_doubles_ascending(const void* a, const void* b)
|
||||
{
|
||||
return compare_doubles(a, b, 1);
|
||||
}
|
||||
|
||||
typedef struct PointStore
|
||||
{
|
||||
double m_lat;
|
||||
double m_lon;
|
||||
double m_dist;
|
||||
double m_value;
|
||||
int m_index;
|
||||
} PointStore;
|
||||
|
||||
/* Comparison function to sort points by distance */
|
||||
static int compare_points(const void* a, const void* b)
|
||||
{
|
||||
PointStore* pA = (PointStore*)a;
|
||||
PointStore* pB = (PointStore*)b;
|
||||
|
||||
if (pA->m_dist < pB->m_dist)
|
||||
return -1;
|
||||
if (pA->m_dist > pB->m_dist)
|
||||
return 1;
|
||||
return 0;
|
||||
return GRIB_SUCCESS;
|
||||
}
|
||||
|
||||
static int find(grib_nearest* nearest, grib_handle* h,
|
||||
|
@ -152,169 +106,31 @@ static int find(grib_nearest* nearest, grib_handle* h,
|
|||
double* values, double* distances, int* indexes, size_t* len)
|
||||
{
|
||||
grib_nearest_polar_stereographic* self = (grib_nearest_polar_stereographic*)nearest;
|
||||
int ret = 0, i = 0;
|
||||
size_t nvalues = 0;
|
||||
long iradius;
|
||||
double radius;
|
||||
grib_iterator* iter = NULL;
|
||||
double lat = 0, lon = 0;
|
||||
return grib_nearest_find_generic(
|
||||
nearest, h, inlat, inlon, flags, /* inputs */
|
||||
|
||||
/* array of candidates for nearest neighbours */
|
||||
PointStore* neighbours = NULL;
|
||||
self->values_key, /* outputs to set the 'self' object */
|
||||
self->radius,
|
||||
self->Ni,
|
||||
self->Nj,
|
||||
&(self->lats),
|
||||
&(self->lats_count),
|
||||
&(self->lons),
|
||||
&(self->lons_count),
|
||||
&(self->distances),
|
||||
|
||||
inlon = normalise_longitude_in_degrees(inlon);
|
||||
|
||||
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;
|
||||
outlats, outlons, /* outputs of the find function */
|
||||
values, distances, indexes, len);
|
||||
}
|
||||
|
||||
static int destroy(grib_nearest* nearest)
|
||||
{
|
||||
grib_nearest_polar_stereographic* self = (grib_nearest_polar_stereographic*)nearest;
|
||||
if (self->lats)
|
||||
grib_context_free(nearest->context, self->lats);
|
||||
if (self->lons)
|
||||
grib_context_free(nearest->context, self->lons);
|
||||
if (self->i)
|
||||
grib_context_free(nearest->context, self->i);
|
||||
if (self->j)
|
||||
grib_context_free(nearest->context, self->j);
|
||||
if (self->k)
|
||||
grib_context_free(nearest->context, self->k);
|
||||
if (self->distances)
|
||||
grib_context_free(nearest->context, self->distances);
|
||||
if (self->lats) grib_context_free(nearest->context, self->lats);
|
||||
if (self->lons) grib_context_free(nearest->context, self->lons);
|
||||
if (self->i) grib_context_free(nearest->context, self->i);
|
||||
if (self->j) grib_context_free(nearest->context, self->j);
|
||||
if (self->k) grib_context_free(nearest->context, self->k);
|
||||
if (self->distances) grib_context_free(nearest->context, self->distances);
|
||||
return GRIB_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -409,7 +409,7 @@ static int find(grib_nearest* nearest, grib_handle* h,
|
|||
kk = 0;
|
||||
for (jj = 0; jj < 2; jj++) {
|
||||
for (ii = 0; ii < 2; ii++) {
|
||||
self->distances[kk] = grib_nearest_distance(radius, inlon, inlat,
|
||||
self->distances[kk] = geographic_distance_spherical(radius, inlon, inlat,
|
||||
self->lons[self->k[kk]], self->lats[self->j[jj]]);
|
||||
kk++;
|
||||
}
|
||||
|
@ -548,7 +548,7 @@ static int find(grib_nearest* nearest, grib_handle* h,
|
|||
kk = 0;
|
||||
for (ii = 0; ii < 2; ii++) {
|
||||
for (jj = 0; jj < 2; jj++) {
|
||||
self->distances[kk] = grib_nearest_distance(radius, inlon, inlat,
|
||||
self->distances[kk] = geographic_distance_spherical(radius, inlon, inlat,
|
||||
self->lons[self->k[kk]], self->lats[self->j[jj]]);
|
||||
kk++;
|
||||
}
|
||||
|
|
|
@ -193,7 +193,7 @@ static int find(grib_nearest* nearest, grib_handle* h,
|
|||
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->distances[kk]=geographic_distance_spherical(radius,inlon,inlat,
|
||||
self->lons[self->i[ii]],self->lats[self->j[jj]]);
|
||||
kk++;
|
||||
}
|
||||
|
@ -409,7 +409,7 @@ static int find(grib_nearest* nearest, grib_handle* h,
|
|||
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->distances[kk] = geographic_distance_spherical(radius, inlon, inlat,
|
||||
self->lons[self->i[ii]], self->lats[self->j[jj]]);
|
||||
kk++;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* (C) Copyright 2005- ECMWF.
|
||||
*
|
||||
* This software is licensed under the terms of the Apache Licence Version 2.0
|
||||
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
|
||||
* virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
|
||||
*/
|
||||
|
||||
#include "grib_api_internal.h"
|
||||
|
||||
/*
|
||||
This is used by make_class.pl
|
||||
|
||||
START_CLASS_DEF
|
||||
CLASS = nearest
|
||||
SUPER = grib_nearest_class_gen
|
||||
IMPLEMENTS = init
|
||||
IMPLEMENTS = find;destroy
|
||||
MEMBERS = double* lats
|
||||
MEMBERS = int lats_count
|
||||
MEMBERS = double* lons
|
||||
MEMBERS = int lons_count
|
||||
MEMBERS = double* distances
|
||||
MEMBERS = int* k
|
||||
MEMBERS = int* i
|
||||
MEMBERS = int* j
|
||||
MEMBERS = const char* Ni
|
||||
MEMBERS = const char* Nj
|
||||
END_CLASS_DEF
|
||||
|
||||
*/
|
||||
|
||||
/* START_CLASS_IMP */
|
||||
|
||||
/*
|
||||
|
||||
Don't edit anything between START_CLASS_IMP and END_CLASS_IMP
|
||||
Instead edit values between START_CLASS_DEF and END_CLASS_DEF
|
||||
or edit "nearest.class" and rerun ./make_class.pl
|
||||
|
||||
*/
|
||||
|
||||
|
||||
static void init_class(grib_nearest_class*);
|
||||
|
||||
static int init(grib_nearest* nearest, grib_handle* h, grib_arguments* args);
|
||||
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);
|
||||
static int destroy(grib_nearest* nearest);
|
||||
|
||||
typedef struct grib_nearest_space_view
|
||||
{
|
||||
grib_nearest nearest;
|
||||
/* Members defined in gen */
|
||||
const char* values_key;
|
||||
const char* radius;
|
||||
int cargs;
|
||||
/* Members defined in space_view */
|
||||
double* lats;
|
||||
int lats_count;
|
||||
double* lons;
|
||||
int lons_count;
|
||||
double* distances;
|
||||
int* k;
|
||||
int* i;
|
||||
int* j;
|
||||
const char* Ni;
|
||||
const char* Nj;
|
||||
} grib_nearest_space_view;
|
||||
|
||||
extern grib_nearest_class* grib_nearest_class_gen;
|
||||
|
||||
static grib_nearest_class _grib_nearest_class_space_view = {
|
||||
&grib_nearest_class_gen, /* super */
|
||||
"space_view", /* name */
|
||||
sizeof(grib_nearest_space_view), /* size of instance */
|
||||
0, /* inited */
|
||||
&init_class, /* init_class */
|
||||
&init, /* constructor */
|
||||
&destroy, /* destructor */
|
||||
&find, /* find nearest */
|
||||
};
|
||||
|
||||
grib_nearest_class* grib_nearest_class_space_view = &_grib_nearest_class_space_view;
|
||||
|
||||
|
||||
static void init_class(grib_nearest_class* c)
|
||||
{
|
||||
}
|
||||
/* END_CLASS_IMP */
|
||||
|
||||
static int init(grib_nearest* nearest, grib_handle* h, grib_arguments* args)
|
||||
{
|
||||
grib_nearest_space_view* self = (grib_nearest_space_view*)nearest;
|
||||
self->Ni = grib_arguments_get_name(h, args, self->cargs++);
|
||||
self->Nj = grib_arguments_get_name(h, args, self->cargs++);
|
||||
self->i = (int*)grib_context_malloc(h->context, 2 * sizeof(int));
|
||||
self->j = (int*)grib_context_malloc(h->context, 2 * sizeof(int));
|
||||
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_space_view* self = (grib_nearest_space_view*)nearest;
|
||||
return grib_nearest_find_generic(
|
||||
nearest, h, inlat, inlon, flags, /* inputs */
|
||||
|
||||
self->values_key, /* outputs to set the 'self' object */
|
||||
self->radius,
|
||||
self->Ni,
|
||||
self->Nj,
|
||||
&(self->lats),
|
||||
&(self->lats_count),
|
||||
&(self->lons),
|
||||
&(self->lons_count),
|
||||
&(self->distances),
|
||||
|
||||
outlats, outlons, /* outputs of the find function */
|
||||
values, distances, indexes, len);
|
||||
}
|
||||
|
||||
static int destroy(grib_nearest* nearest)
|
||||
{
|
||||
grib_nearest_space_view* self = (grib_nearest_space_view*)nearest;
|
||||
if (self->lats) grib_context_free(nearest->context, self->lats);
|
||||
if (self->lons) grib_context_free(nearest->context, self->lons);
|
||||
if (self->i) grib_context_free(nearest->context, self->i);
|
||||
if (self->j) grib_context_free(nearest->context, self->j);
|
||||
if (self->k) grib_context_free(nearest->context, self->k);
|
||||
if (self->distances) grib_context_free(nearest->context, self->distances);
|
||||
return GRIB_SUCCESS;
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
/* This file is automatically generated by ./make_class.pl, do not edit */
|
||||
{ "gen", &grib_nearest_class_gen, },
|
||||
{ "lambert_azimuthal_equal_area", &grib_nearest_class_lambert_azimuthal_equal_area, },
|
||||
{ "lambert_conformal", &grib_nearest_class_lambert_conformal, },
|
||||
{ "latlon_reduced", &grib_nearest_class_latlon_reduced, },
|
||||
{ "mercator", &grib_nearest_class_mercator, },
|
||||
{ "polar_stereographic", &grib_nearest_class_polar_stereographic, },
|
||||
{ "reduced", &grib_nearest_class_reduced, },
|
||||
{ "regular", &grib_nearest_class_regular, },
|
||||
{ "sh", &grib_nearest_class_sh, },
|
||||
{ "space_view", &grib_nearest_class_space_view, },
|
||||
|
|
|
@ -69,6 +69,7 @@ list(APPEND tests_no_data_reqd
|
|||
grib_sh_imag
|
||||
pseudo_diag
|
||||
grib_lambert_conformal
|
||||
grib_space_view
|
||||
grib_g1fcperiod)
|
||||
|
||||
# These tests do require data downloads
|
||||
|
|
|
@ -57,6 +57,7 @@ TESTS = definitions.sh \
|
|||
grib_padding.sh \
|
||||
grib_lamb_az_eq_area.sh \
|
||||
grib_lambert_conformal.sh \
|
||||
grib_space_view.sh \
|
||||
grib_mercator.sh \
|
||||
grib_to_netcdf.sh \
|
||||
grib_dump_debug.sh \
|
||||
|
|
|
@ -55,5 +55,9 @@ diff $DATA_OUTFILE $REF_FILE
|
|||
grib_check_key_equals $GRIB_OUTFILE standardParallelInDegrees,centralLongitudeInDegrees '48 9'
|
||||
grib_check_key_equals $GRIB_OUTFILE xDirectionGridLengthInMetres,yDirectionGridLengthInMetres '5000 5000'
|
||||
|
||||
# Nearest
|
||||
${tools_dir}/grib_ls -l 67,-33,1 $GRIB_OUTFILE
|
||||
|
||||
|
||||
# Clean up
|
||||
rm -f $FILTER_FILE $GRIB_OUTFILE $DATA_OUTFILE
|
||||
|
|
|
@ -52,7 +52,6 @@ ${tools_dir}/grib_ls -l 50,0 $tempGrib
|
|||
cat > $tempFilter <<EOF
|
||||
set gridType="lambert";
|
||||
set numberOfDataPoints=294000;
|
||||
set shapeOfTheEarth=6;
|
||||
set Nx=588;
|
||||
set Ny=500;
|
||||
set latitudeOfFirstGridPoint=40442000;
|
||||
|
@ -63,7 +62,7 @@ cat > $tempFilter <<EOF
|
|||
set Dy=2499000;
|
||||
set Latin1=46401000;
|
||||
set Latin2=46401000;
|
||||
set shapeOfTheEarth=2;
|
||||
set shapeOfTheEarth=2; # oblate earth
|
||||
set numberOfValues=294000;
|
||||
write;
|
||||
EOF
|
||||
|
@ -76,10 +75,11 @@ if [ ! -f "$tempGrib" ]; then
|
|||
fi
|
||||
grib_check_key_equals $tempGrib 'earthIsOblate,earthMinorAxisInMetres,earthMajorAxisInMetres' '1 6356775 6378160'
|
||||
|
||||
# Invoke Geoiterator on the newly created GRIB file
|
||||
# Invoke Geoiterator on the oblate lambert GRIB
|
||||
${tools_dir}/grib_get_data $tempGrib > $tempOut
|
||||
|
||||
|
||||
# Nearest neighbour on the oblate lambert GRIB
|
||||
${tools_dir}/grib_ls -l 40.44,353.56 $tempGrib
|
||||
|
||||
|
||||
# Clean up
|
||||
|
|
|
@ -132,6 +132,15 @@ ${tools_dir}/grib_set -s localDefinitionNumber=49,type=35 $sample_g1 $temp
|
|||
grib_check_key_equals $temp 'perturbationNumber,numberOfForecastsInEnsemble' '0 0'
|
||||
|
||||
|
||||
# Local Definition 39 and type 'eme' for GRIB2
|
||||
# --------------------------------------------
|
||||
${tools_dir}/grib_set -s \
|
||||
setLocalDefinition=1,localDefinitionNumber=39,type=eme,stream=elda,componentIndex=11,offsetToEndOf4DvarWindow=12 \
|
||||
$sample_g2 $temp
|
||||
grib_check_key_equals $temp 'mars.number,mars.anoffset' '11 12'
|
||||
${tools_dir}/grib_set -s setLocalDefinition=1,localDefinitionNumber=39,type=eme,stream=enda,componentIndex=11 $sample_g2 $temp
|
||||
grib_check_key_equals $temp 'mars.number' '11'
|
||||
|
||||
|
||||
# Local Definition 18 (list of ascii keys)
|
||||
# ----------------------------------------
|
||||
|
|
|
@ -30,5 +30,9 @@ EOF
|
|||
|
||||
${tools_dir}/grib_filter $tempFilter $input
|
||||
|
||||
# Nearest function
|
||||
${tools_dir}/grib_ls -l 19,-97,1 $input > $tempOut
|
||||
grep -q "Point chosen #1 index=618" $tempOut
|
||||
|
||||
# Clean up
|
||||
rm -f $tempFilter $tempOut
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
#!/bin/sh
|
||||
# (C) Copyright 2005- ECMWF.
|
||||
#
|
||||
# This software is licensed under the terms of the Apache Licence Version 2.0
|
||||
# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
|
||||
# virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
|
||||
|
||||
. ./include.sh
|
||||
|
||||
# Define a common label for all the tmp files
|
||||
label="grib_space_view_test"
|
||||
tempFilter="temp.${label}.filt"
|
||||
tempGrib="temp.${label}.grib"
|
||||
tempOut="temp.${label}.out"
|
||||
|
||||
input=$ECCODES_SAMPLES_PATH/GRIB2.tmpl
|
||||
|
||||
# Create a filter
|
||||
cat > $tempFilter <<EOF
|
||||
set gridType="space_view";
|
||||
set Nx=1900;
|
||||
set Ny=900;
|
||||
set dx=3622;
|
||||
set dy=3610;
|
||||
set Xp=764000;
|
||||
set Yp=1774000;
|
||||
set Nr=6610700;
|
||||
set numberOfDataPoints=1710000; # 1900 x 900
|
||||
set numberOfValues=1710000;
|
||||
write;
|
||||
EOF
|
||||
|
||||
# Use filter on input to create a new GRIB
|
||||
${tools_dir}/grib_filter -o $tempGrib $tempFilter $input
|
||||
if [ ! -f "$tempGrib" ]; then
|
||||
echo 'Failed to create output GRIB from filter' >&2
|
||||
exit 1
|
||||
fi
|
||||
# Invoke Geoiterator on the newly created GRIB file
|
||||
${tools_dir}/grib_get_data $tempGrib > $tempOut
|
||||
|
||||
${tools_dir}/grib_ls -l 50,0 $tempGrib
|
||||
|
||||
|
||||
# Clean up
|
||||
rm -f $tempFilter $tempGrib $tempOut
|
|
@ -156,14 +156,14 @@ int grib_tool_init(grib_runtime_options* options)
|
|||
|
||||
options->latlon_idx = -1;
|
||||
max = options->distances[0];
|
||||
for (i = 0; i < 4; i++)
|
||||
for (i = 0; i < LATLON_SIZE; i++)
|
||||
if (max < options->distances[i]) {
|
||||
max = options->distances[i];
|
||||
}
|
||||
min = max;
|
||||
min_overall = max;
|
||||
/* See GRIB-213 */
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (i = 0; i < LATLON_SIZE; i++) {
|
||||
if (min_overall >= options->distances[i]) { /* find overall min and index ignoring mask */
|
||||
min_overall = options->distances[i];
|
||||
idx_overall = i;
|
||||
|
@ -184,7 +184,7 @@ int grib_tool_init(grib_runtime_options* options)
|
|||
if (options->latlon_idx < 0) {
|
||||
min = 0;
|
||||
options->latlon_idx = 0;
|
||||
for (i = 1; i < 4; i++)
|
||||
for (i = 1; i < LATLON_SIZE; i++)
|
||||
if (min > options->distances[i]) {
|
||||
min = options->distances[i];
|
||||
options->latlon_idx = i;
|
||||
|
@ -307,7 +307,7 @@ int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h)
|
|||
if (!options->latlon_mask) {
|
||||
min = options->distances[0];
|
||||
options->latlon_idx = 0;
|
||||
for (i = 1; i < 4; i++) {
|
||||
for (i = 1; i < LATLON_SIZE; i++) {
|
||||
if (min > options->distances[i]) {
|
||||
min = options->distances[i];
|
||||
options->latlon_idx = i;
|
||||
|
@ -330,7 +330,7 @@ int grib_tool_new_handle_action(grib_runtime_options* options, grib_handle* h)
|
|||
else
|
||||
printf("\"nearest\"");
|
||||
printf("\n, \"neighbours\" : ");
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (i = 0; i < LATLON_SIZE; i++) {
|
||||
printf("%s", s);
|
||||
len = MAX_STRING_LEN;
|
||||
printf(
|
||||
|
@ -398,15 +398,16 @@ int grib_tool_finalise_action(grib_runtime_options* options)
|
|||
int i = 0;
|
||||
if (options->latlon && options->verbose) {
|
||||
printf("Input Point: latitude=%.2f longitude=%.2f\n", lat, lon);
|
||||
printf("Grid Point chosen #%d index=%d latitude=%.2f longitude=%.2f distance=%.2f (Km)\n",
|
||||
options->latlon_idx + 1, (int)options->indexes[options->latlon_idx],
|
||||
options->lats[options->latlon_idx],
|
||||
options->lons[options->latlon_idx],
|
||||
options->distances[options->latlon_idx]);
|
||||
|
||||
if (options->latlon_idx >= 0 && options->latlon_idx < LATLON_SIZE) {
|
||||
printf("Grid Point chosen #%d index=%d latitude=%.2f longitude=%.2f distance=%.2f (Km)\n",
|
||||
options->latlon_idx + 1, (int)options->indexes[options->latlon_idx],
|
||||
options->lats[options->latlon_idx],
|
||||
options->lons[options->latlon_idx],
|
||||
options->distances[options->latlon_idx]);
|
||||
}
|
||||
if (options->latlon_mask) {
|
||||
printf("Mask values:\n");
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (i = 0; i < LATLON_SIZE; i++) {
|
||||
printf("- %d - index=%d latitude=%.2f longitude=%.2f distance=%.2f (Km) value=%.2f\n",
|
||||
i + 1, (int)options->indexes[i], options->lats[i], options->lons[i],
|
||||
options->distances[i], options->mask_values[i]);
|
||||
|
@ -414,7 +415,7 @@ int grib_tool_finalise_action(grib_runtime_options* options)
|
|||
}
|
||||
else {
|
||||
printf("Other grid Points\n");
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (i = 0; i < LATLON_SIZE; i++) {
|
||||
printf("- %d - index=%d latitude=%.2f longitude=%.2f distance=%.2f (Km)\n",
|
||||
i + 1, (int)options->indexes[i], options->lats[i], options->lons[i],
|
||||
options->distances[i]);
|
||||
|
|
|
@ -1170,7 +1170,7 @@ void grib_print_key_values(grib_runtime_options* options, grib_handle* h)
|
|||
if (options->latlon) {
|
||||
if (options->latlon_mode == 4) {
|
||||
int ii = 0;
|
||||
for (ii = 0; ii < 4; ii++) {
|
||||
for (ii = 0; ii < LATLON_SIZE; ii++) {
|
||||
fprintf(dump_file, options->format, options->values[ii]);
|
||||
fprintf(dump_file, " ");
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#define MAX_STRING_LEN 512
|
||||
#define MAX_FAILED 1024
|
||||
#define MAX_CONSTRAINT_VALUES 500
|
||||
#define LATLON_SIZE 4 /* nearest */
|
||||
|
||||
#define MODE_GRIB 0
|
||||
#define MODE_GTS 1
|
||||
|
@ -140,15 +141,15 @@ typedef struct grib_runtime_options
|
|||
int gts;
|
||||
char* orderby;
|
||||
char* latlon;
|
||||
double lats[4];
|
||||
double lons[4];
|
||||
double values[4];
|
||||
double distances[4];
|
||||
int indexes[4];
|
||||
double lats[LATLON_SIZE];
|
||||
double lons[LATLON_SIZE];
|
||||
double values[LATLON_SIZE];
|
||||
double distances[LATLON_SIZE];
|
||||
int indexes[LATLON_SIZE];
|
||||
int latlon_mode;
|
||||
char* latlon_mask;
|
||||
int latlon_idx;
|
||||
double mask_values[4];
|
||||
double mask_values[LATLON_SIZE];
|
||||
int index;
|
||||
int index_on;
|
||||
double constant;
|
||||
|
|
|
@ -3,7 +3,7 @@ PACKAGE_NAME='eccodes'
|
|||
|
||||
# Package version
|
||||
ECCODES_MAJOR_VERSION=2
|
||||
ECCODES_MINOR_VERSION=18
|
||||
ECCODES_MINOR_VERSION=19
|
||||
ECCODES_REVISION_VERSION=0
|
||||
|
||||
ECCODES_CURRENT=1
|
||||
|
|
|
@ -511,12 +511,15 @@
|
|||
<ClCompile Include="..\..\..\src\grib_nearest.c" />
|
||||
<ClCompile Include="..\..\..\src\grib_nearest_class.c" />
|
||||
<ClCompile Include="..\..\..\src\grib_nearest_class_gen.c" />
|
||||
<ClCompile Include="..\..\..\src\grib_nearest_class_lambert_azimuthal_equal_area.c" />
|
||||
<ClCompile Include="..\..\..\src\grib_nearest_class_lambert_conformal.c" />
|
||||
<ClCompile Include="..\..\..\src\grib_nearest_class_latlon_reduced.c" />
|
||||
<ClCompile Include="..\..\..\src\grib_nearest_class_mercator.c" />
|
||||
<ClCompile Include="..\..\..\src\grib_nearest_class_polar_stereographic.c" />
|
||||
<ClCompile Include="..\..\..\src\grib_nearest_class_reduced.c" />
|
||||
<ClCompile Include="..\..\..\src\grib_nearest_class_regular.c" />
|
||||
<ClCompile Include="..\..\..\src\grib_nearest_class_sh.c" />
|
||||
<ClCompile Include="..\..\..\src\grib_nearest_class_space_view.c" />
|
||||
<ClCompile Include="..\..\..\src\grib_oarray.c" />
|
||||
<ClCompile Include="..\..\..\src\grib_openjpeg_encoding.c" />
|
||||
<ClCompile Include="..\..\..\src\grib_optimize_decimal_factor.c" />
|
||||
|
|
Loading…
Reference in New Issue