diff --git a/definitions/grib2/templates/template.3.101.def b/definitions/grib2/templates/template.3.101.def index fb8cb71f1..7908cf421 100644 --- a/definitions/grib2/templates/template.3.101.def +++ b/definitions/grib2/templates/template.3.101.def @@ -14,3 +14,5 @@ unsigned[1] numberOfGridInReference : dump; byte[16] uuidOfHGrid : dump; template_nofail unstructuredGrid "grib2/localConcepts/[centre:s]/unstructuredGrid.def"; + +# iterator unstructured(numberOfPoints, missingValue, values, uuidOfHGrid); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7700ba16e..01d497bb1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -350,6 +350,7 @@ list( APPEND eccodes_src_files geo_iterator/grib_iterator_class_polar_stereographic.cc geo_iterator/grib_iterator_class_regular.cc geo_iterator/grib_iterator_class_space_view.cc + geo_iterator/grib_iterator_class_unstructured.cc grib_expression.cc codes_util.cc grib_util.cc diff --git a/src/geo_iterator/grib_iterator_class_unstructured.cc b/src/geo_iterator/grib_iterator_class_unstructured.cc new file mode 100644 index 000000000..dab834c12 --- /dev/null +++ b/src/geo_iterator/grib_iterator_class_unstructured.cc @@ -0,0 +1,73 @@ +/* + * (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_iterator_class_unstructured.h" + +eccodes::geo_iterator::Unstructured _grib_iterator_unstructured{}; +eccodes::geo_iterator::Iterator* grib_iterator_unstructured = &_grib_iterator_unstructured; + +namespace eccodes::geo_iterator { + +#define ITER "Unstructured grid Geoiterator" + +int Unstructured::next(double* lat, double* lon, double* val) const +{ + if ((long)e_ >= (long)(nv_ - 1)) + return 0; + e_++; + + *lat = lats_[e_]; + *lon = lons_[e_]; + if (val && data_) { + *val = data_[e_]; + } + return 1; +} + +int Unstructured::init(grib_handle* h, grib_arguments* args) +{ + int ret = GRIB_SUCCESS; + if ((ret = Gen::init(h, args)) != GRIB_SUCCESS) + return ret; + + const char* s_uuidOfHGrid = grib_arguments_get_name(h, args, carg_++); + char uuidOfHGrid[32] = {0,}; + auto slen = sizeof(uuidOfHGrid); + if ((ret = grib_get_string_internal(h, s_uuidOfHGrid, uuidOfHGrid, &slen)) != GRIB_SUCCESS) { + return ret; + } + + lats_ = (double*)grib_context_malloc(h->context, nv_ * sizeof(double)); + if (!lats_) { + grib_context_log(h->context, GRIB_LOG_ERROR, "%s: Error allocating %zu bytes", ITER, nv_ * sizeof(double)); + return GRIB_OUT_OF_MEMORY; + } + lons_ = (double*)grib_context_malloc(h->context, nv_ * sizeof(double)); + if (!lons_) { + grib_context_log(h->context, GRIB_LOG_ERROR, "%s: Error allocating %zu bytes", ITER, nv_ * sizeof(double)); + return GRIB_OUT_OF_MEMORY; + } + + e_ = -1; + + return ret; +} + +int Unstructured::destroy() +{ + DEBUG_ASSERT(h_); + const grib_context* c = h_->context; + grib_context_free(c, lats_); + grib_context_free(c, lons_); + + return Gen::destroy(); +} + +} // namespace eccodes::geo_iterator diff --git a/src/geo_iterator/grib_iterator_class_unstructured.h b/src/geo_iterator/grib_iterator_class_unstructured.h new file mode 100644 index 000000000..3e99e0166 --- /dev/null +++ b/src/geo_iterator/grib_iterator_class_unstructured.h @@ -0,0 +1,29 @@ +/* + * (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. + */ + +#pragma once + +#include "grib_iterator_class_gen.h" + +namespace eccodes::geo_iterator { + +class Unstructured : public Gen +{ +public: + Unstructured() : + Gen() { class_name_ = "unstructured"; } + Iterator* create() const override { return new Unstructured(); } + + int init(grib_handle*, grib_arguments*) override; + int next(double*, double*, double*) const override; + int destroy() override; +}; + +} // namespace eccodes::geo_iterator diff --git a/src/grib_iterator_factory.cc b/src/grib_iterator_factory.cc index 9c5fc31dc..9ea143b3d 100644 --- a/src/grib_iterator_factory.cc +++ b/src/grib_iterator_factory.cc @@ -57,6 +57,7 @@ static const struct table_entry table[] = { { "polar_stereographic", &grib_iterator_polar_stereographic, }, { "regular", &grib_iterator_regular, }, { "space_view", &grib_iterator_space_view, }, + { "unstructured", &grib_iterator_unstructured, }, }; eccodes::geo_iterator::Iterator* grib_iterator_factory(grib_handle* h, grib_arguments* args, unsigned long flags, int* error) diff --git a/src/grib_iterator_factory.h b/src/grib_iterator_factory.h index 256c204e6..b45f6cfe0 100644 --- a/src/grib_iterator_factory.h +++ b/src/grib_iterator_factory.h @@ -24,6 +24,7 @@ extern eccodes::geo_iterator::Iterator* grib_iterator_mercator; extern eccodes::geo_iterator::Iterator* grib_iterator_polar_stereographic; extern eccodes::geo_iterator::Iterator* grib_iterator_regular; extern eccodes::geo_iterator::Iterator* grib_iterator_space_view; +extern eccodes::geo_iterator::Iterator* grib_iterator_unstructured; eccodes::geo_iterator::Iterator* grib_iterator_factory(grib_handle* h, grib_arguments* args, unsigned long flags, int* error);