OpenCPN Partial API docs
Loading...
Searching...
No Matches
grib_record.h
Go to the documentation of this file.
1/**********************************************************************
2zyGrib: meteorological GRIB file viewer
3Copyright (C) 2008 - Jacques Zaninetti - http://www.zygrib.org
4
5This program is free software: you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation, either version 3 of the License, or
8(at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program. If not, see <http://www.gnu.org/licenses/>.
17***********************************************************************/
18
30#ifndef GRIBRECORD_H
31#define GRIBRECORD_H
32
33#include <iostream>
34#include <cmath>
35
36#define DEBUG_INFO false
37#define DEBUG_ERROR true
38#define grib_debug(format, ...) \
39 { \
40 if (DEBUG_INFO) { \
41 fprintf(stderr, format, __VA_ARGS__); \
42 fprintf(stderr, "\n"); \
43 } \
44 }
45#define erreur(format, ...) \
46 { \
47 if (DEBUG_ERROR) { \
48 fprintf(stderr, "Grib ERROR: "); \
49 fprintf(stderr, format, __VA_ARGS__); \
50 fprintf(stderr, "\n"); \
51 } \
52 }
53
54#define zuint unsigned int
55#define zuchar unsigned char
56
57#define GRIB_NOTDEF (-999999999)
58
59//--------------------------------------------------------
60// dataTypes Cf function translateDataType()
61//--------------------------------------------------------
62#define GRB_PRESSURE 2 /* Pa */
63#define GRB_GEOPOT_HGT 7 /* gpm */
64#define GRB_TEMP 11 /* K */
65#define GRB_TPOT 13 /* K */
66#define GRB_TMAX 15 /* K */
67#define GRB_TMIN 16 /* K */
68#define GRB_DEWPOINT 17 /* K */
69
70#define GRB_WIND_DIR 31 /* Deg. Wind Direction */
71#define GRB_WIND_SPEED 32 /* m/s Wind Speed */
72#define GRB_WIND_VX 33 /* m/s U */
73#define GRB_WIND_VY 34 /* m/s V */
74
75#define GRB_CUR_DIR 47 /* Deg. Direction of current */
76#define GRB_CUR_SPEED 48 /* m/s Speed of current */
77#define GRB_UOGRD 49 /*"u-component of current", "m/s" */
78#define GRB_VOGRD 50 /*"v-component of current", "m/s" */
79
80#define GRB_HUMID_SPEC 51 /* kg/kg */
81#define GRB_HUMID_REL 52 /* % */
82#define GRB_PRECIP_RATE 59 /* l/m2/s */
83#define GRB_PRECIP_TOT 61 /* l/m2 */
84#define GRB_SNOW_DEPTH 66 /* m */
85#define GRB_CLOUD_TOT 71 /* % */
86#define GRB_HTSGW 100 /* m */
87#define GRB_WTMP 80 /* "Water Temperature", "K" */
88#define GRB_COMP_REFL 212 /* dBZ */
89
90#define GRB_WVDIR 101
91#define GRB_WVHGT 102
92#define GRB_WVPER 103
93#define GRB_SWDIR 104
94#define GRB_SWELL 105
95#define GRB_SWPER 106
96#define GRB_DIRPW 107
97#define GRB_PERPW 108
98#define GRB_DIRSW 109
99#define GRB_PERSW 110
100#define GRB_PER 209
101#define GRB_DIR 210
102
103#define GRB_CRAIN 140 /* "Categorical rain", "yes=1;no=0" */
104#define GRB_FRZRAIN_CATEG 141 /* 1=yes 0=no */
105#define GRB_SNOW_CATEG 143 /* 1=yes 0=no */
106#define GRB_CAPE 157 /* J/kg */
107
108#define GRB_TSEC \
109 171 /* "Seconds prior to initial reference time (defined in bytes 18-20)" */
110#define GRB_WIND_GUST 180 /* m/s "wind gust */
111#define GRB_WIND_GUST_VX 181 /* m/s */
112#define GRB_WIND_GUST_VY 182 /* m/s */
113
114#define GRB_USCT 190 /* Scatterometer estimated U Wind, NCEP Center 7 */
115#define GRB_VSCT 191 /* Scatterometer estimated V Wind, NCEP Center 7 */
116
117#define GRB_WIND_XY2D 250 /* private : GRB_WIND_VX+GRB_WIND_VX */
118#define GRB_DIFF_TEMPDEW 251 /* private : GRB_TEMP-GRB_DEWPOINT */
119
120//--------------------------------------------------------
121// Levels types (altitude reference)
122//--------------------------------------------------------
123#define LV_GND_SURF 1
124#define LV_ISOTHERM0 4
125#define LV_ISOBARIC 100
126#define LV_MSL 102
127#define LV_ABOV_MSL 103
128#define LV_ABOV_GND 105
129#define LV_SIGMA 107
130#define LV_ATMOS_ENT 10
131#define LV_ATMOS_ALL 200
132
133//---------------------------------------------------------
134enum DataCenterModel {
135 NOAA_GFS,
136 NOAA_NCEP_WW3,
137 NOAA_NCEP_SST,
138 NOAA_RTOFS,
139 FNMOC_WW3_GLB,
140 FNMOC_WW3_MED,
141 NORWAY_METNO,
142 ECMWF_ERA5,
143 KNMI_HIRLAM,
144 KNMI_HARMONIE_AROME,
145 OTHER_DATA_CENTER
146};
147
148//----------------------------------------------
149class GribCode {
150public:
151 static zuint makeCode(zuchar dataType, zuchar levelType, zuint levelValue) {
152 return ((levelValue & 0xFFFF) << 16) + ((levelType & 0xFF) << 8) + dataType;
153 }
154 static zuchar getDataType(zuint code) { return code & 0xFF; }
155 static zuchar getLevelType(zuint code) { return (code >> 8) & 0xFF; }
156 static zuint getLevelValue(zuint code) { return (code >> 16) & 0xFFFF; }
157};
158
187public:
189 GribRecord(const GribRecord &rec);
190 GribRecord() { is_filled = false; }
191
192 virtual ~GribRecord();
193
225 static GribRecord *InterpolatedRecord(const GribRecord &rec1,
226 const GribRecord &rec2, double d,
227 bool dir = false);
254 const GribRecord &rec1x,
255 const GribRecord &rec1y,
256 const GribRecord &rec2x,
257 const GribRecord &rec2y, double d);
258
259 static GribRecord *MagnitudeRecord(const GribRecord &rec1,
260 const GribRecord &rec2);
261
275 static void Polar2UV(GribRecord *pDIR, GribRecord *pSPEED);
276
277 void multiplyAllData(double k);
278 void Substract(const GribRecord &rec, bool positive = true);
279 void Average(const GribRecord &rec);
280
281 [[nodiscard]] bool IsOk() const { return ok; };
282 [[nodiscard]] bool IsDataKnown() const { return known_data; };
283 [[nodiscard]] bool IsEof() const { return eof; };
284 [[nodiscard]] bool isDuplicated() const { return is_duplicated; };
302 [[nodiscard]] zuchar GetDataType() const { return data_type; }
303 void SetDataType(zuchar t);
304
319 [[nodiscard]] zuchar GetLevelType() const { return level_type; }
332 [[nodiscard]] zuint GetLevelValue() const { return level_value; }
352 [[nodiscard]] zuint GetDataCenterModel() const { return data_center_model; }
353 //-----------------------------------------
354
368 [[nodiscard]] zuchar GetIdCenter() const { return id_center; }
380 [[nodiscard]] zuchar GetIdModel() const { return id_model; }
391 [[nodiscard]] zuchar GetIdGrid() const { return id_grid; }
392
393 //-----------------------------------------
394 [[nodiscard]] std::string GetKey() const { return data_key; }
395 static std::string MakeKey(int dataType, int levelType, int levelValue);
396
397 //-----------------------------------------
409 [[nodiscard]] int GetPeriodP1() const { return static_cast<int>(period_p1); }
421 [[nodiscard]] int GetPeriodP2() const { return static_cast<int>(period_p2); }
431 [[nodiscard]] zuint GetPeriodSec() const { return periodsec; }
444 [[nodiscard]] zuchar GetTimeRange() const { return time_range; }
445
446 // Number of points in the grid
452 [[nodiscard]] int GetNi() const { return static_cast<int>(Ni); }
458 [[nodiscard]] int GetNj() const { return static_cast<int>(Nj); }
464 [[nodiscard]] double GetDi() const { return Di; }
471 [[nodiscard]] double GetDj() const { return Dj; }
472
484 [[nodiscard]] double GetValue(int i, int j) const { return data[j * Ni + i]; }
485
486 void SetValue(zuint i, zuint j, double v) {
487 if (i < Ni && j < Nj) data[j * Ni + i] = v;
488 }
489
503 [[nodiscard]] double GetInterpolatedValue(double px, double py,
504 bool numericalInterpolation = true,
505 bool dir = false) const;
506
531 static bool GetInterpolatedValues(double &M, double &A, const GribRecord *GRX,
532 const GribRecord *GRY, double px, double py,
533 bool numericalInterpolation = true);
534
544 [[nodiscard]] inline double GetX(int i) const { return Lo1 + i * Di; }
555 [[nodiscard]] inline double GetY(int j) const { return La1 + j * Dj; }
566 void getXY(int i, int j, double *x, double *y) const {
567 *x = GetX(i);
568 *y = GetY(j);
569 };
570
571 [[nodiscard]] double GetLatMin() const { return lat_min; }
572 [[nodiscard]] double GetLonMin() const { return lon_min; }
573 [[nodiscard]] double GetLatMax() const { return lat_max; }
574 [[nodiscard]] double GetLonMax() const { return lon_max; }
575
576 // Is there a value at a particular grid point ?
577 [[nodiscard]] inline bool HasValue(int i, int j) const;
578 // Is there a value that is not GRIB_NOTDEF ?
579 [[nodiscard]] inline bool IsDefined(int i, int j) const {
580 return HasValue(i, j) && GetValue(i, j) != GRIB_NOTDEF;
581 }
582
583 // Reference date Date (file creation date)
584 [[nodiscard]] time_t GetRecordRefDate() const { return ref_date; }
585 [[nodiscard]] const char *GetStrRecordRefDate() const { return str_ref_date; }
586
587 // Date courante des prévisions
588 [[nodiscard]] time_t GetRecordCurrentDate() const { return cur_date; }
589 [[nodiscard]] const char *GetStrRecordCurDate() const { return str_cur_date; }
590 void SetRecordCurrentDate(time_t t);
591 void Print() const;
592 [[nodiscard]] bool IsFilled() const { return is_filled; }
593 void SetFilled(bool val = true) { is_filled = val; }
594
595private:
596 // Is a point within the extent of the grid?
597 [[nodiscard]] inline bool IsPointInMap(double x, double y) const;
598 [[nodiscard]] inline bool IsXInMap(double x) const;
599 [[nodiscard]] inline bool IsYInMap(double y) const;
600
601protected:
602 // private:
603 static bool GetInterpolatedParameters(const GribRecord &rec1,
604 const GribRecord &rec2, double &La1,
605 double &Lo1, double &La2, double &Lo2,
606 double &Di, double &Dj, int &im1,
607 int &jm1, int &im2, int &jm2, int &Ni,
608 int &Nj, int &rec1offi, int &rec1offj,
609 int &rec2offi, int &rec2offj);
610
617 int id;
625 bool ok;
647 bool eof;
652 std::string data_key;
653 char str_ref_date[32];
654 char str_cur_date[32];
673
674 //---------------------------------------------
675 // SECTION 0: THE INDICATOR SECTION (IS)
676 //---------------------------------------------
682
683 // SECTION 1: THE PRODUCT DEFINITION SECTION (PDS)
688 zuchar id_center;
693 zuchar id_model;
698 zuchar id_grid;
703 zuchar data_type; // octet 9 = parameters and units
715
720 bool hasBMS;
725 zuint refyear, refmonth, refday, refhour, refminute;
726 // zuchar period_p1, period_p2;
731 zuint period_p1, period_p2;
746 time_t ref_date;
750 time_t cur_date;
751 // SECTION 2: THE GRID DESCRIPTION SECTION (GDS)
752 zuchar NV, PV;
753 zuchar grid_type;
754 zuint Ni, Nj;
755 double La1, Lo1;
756 double La2, Lo2;
757 double lat_min, lon_min, lat_max, lon_max;
758 double Di, Dj;
759 zuchar resol_flags, scan_flags;
760 bool has_di_dj;
761 bool is_earth_spheric;
762 bool is_ueast_vnorth;
763 bool is_scan_i_positive;
764 bool is_scan_j_positive;
765 bool is_adjacent_i;
766 // SECTION 3: BIT MAP SECTION (BMS)
767 zuint bms_size;
768 zuchar *bms_bits;
769 // SECTION 4: BINARY DATA SECTION (BDS)
770 double *data;
771 // SECTION 5: END SECTION (ES)
772
773 time_t MakeDate(zuint year, zuint month, zuint day, zuint hour, zuint min,
774 zuint sec);
775
776 // void print();
777};
778
779//==========================================================================
780inline bool GribRecord::HasValue(int i, int j) const {
781 // is data present in BMS ?
782 if (!hasBMS) {
783 return true;
784 }
785 int bit;
786 if (is_adjacent_i) {
787 bit = static_cast<int>(j * Ni + i);
788 } else {
789 bit = static_cast<int>(i * Nj + j);
790 }
791 zuchar c = bms_bits[bit / 8];
792 zuchar m = static_cast<zuchar>(128) >> (bit % 8);
793 return (m & c) != 0;
794}
795
796//-----------------------------------------------------------------
797inline bool GribRecord::IsPointInMap(double x, double y) const {
798 return IsXInMap(x) && IsYInMap(y);
799 /* if (Dj < 0)
800 return x>=Lo1 && y<=La1 && x<=Lo1+(Ni-1)*Di && y>=La1+(Nj-1)*Dj;
801 else
802 return x>=Lo1 && y>=La1 && x<=Lo1+(Ni-1)*Di && y<=La1+(Nj-1)*Dj;*/
803}
804//-----------------------------------------------------------------
805inline bool GribRecord::IsXInMap(double x) const {
806 // return x>=Lo1 && x<=Lo1+(Ni-1)*Di;
807 // printf ("%f %f %f\n", Lo1, Lo2, x);
808 if (Di > 0) {
809 double maxLo = Lo2;
810 if (Lo2 + Di >= 360) /* grib that covers the whole world */
811 maxLo += Di;
812 return x >= Lo1 && x <= maxLo;
813 } else {
814 double maxLo = Lo1;
815 if (Lo2 + Di >= 360) /* grib that covers the whole world */
816 maxLo += Di;
817 return x >= Lo2 && x <= maxLo;
818 }
819}
820//-----------------------------------------------------------------
821inline bool GribRecord::IsYInMap(double y) const {
822 if (Dj < 0)
823 return y <= La1 && y >= La2;
824 else
825 return y >= La1 && y <= La2;
826}
827
828#endif
A meteorological data grid from a GRIB (Gridded Binary) file.
int GetNj() const
Returns the number of points in the latitude (j) direction of the grid.
static bool GetInterpolatedValues(double &M, double &A, const GribRecord *GRX, const GribRecord *GRY, double px, double py, bool numericalInterpolation=true)
Gets spatially interpolated wind or current vector values at a specific latitude/longitude point.
bool eof
Signals when the end of the GRIB file has been reached during parsing.
zuint periodsec
Forecast period in seconds.
static void Polar2UV(GribRecord *pDIR, GribRecord *pSPEED)
Converts wind or current values from polar (direction/speed) to cartesian (U/V) components.
time_t cur_date
Unix timestamp of when this forecast is valid.
bool is_duplicated
Indicates if this record was created through copying rather than direct reading.
zuchar GetTimeRange() const
Returns the time range indicator that defines how P1 and P2 should be interpreted.
zuint GetDataCenterModel() const
Returns the numerical weather prediction model/center that produced this data.
void getXY(int i, int j, double *x, double *y) const
Converts grid indices to longitude/latitude coordinates.
double Lo2
Grid end coordinates.
zuint period_p1
Time range indicators for this forecast step.
double GetY(int j) const
Converts grid index j to latitude in degrees.
double Lo1
Grid origin coordinates.
bool is_filled
Indicates whether the data array has been populated.
zuchar GetIdModel() const
Returns the model/process ID within the originating center.
static GribRecord * Interpolated2DRecord(GribRecord *&rety, const GribRecord &rec1x, const GribRecord &rec1y, const GribRecord &rec2x, const GribRecord &rec2y, double d)
Creates temporally interpolated records for vector fields (wind, currents).
int GetPeriodP2() const
Returns the end of the period (P2) used for this record.
zuchar id_model
Model identifier within the originating center.
zuchar GetDataType() const
Returns the type of meteorological parameter stored in this grid.
double GetValue(int i, int j) const
Returns the data value at a specific grid point.
double GetX(int i) const
Converts grid index i to longitude in degrees.
std::string data_key
Unique string identifier constructed from data type, level type, and level value.
zuint GetPeriodSec() const
Returns the forecast period in seconds from reference time.
static GribRecord * InterpolatedRecord(const GribRecord &rec1, const GribRecord &rec2, double d, bool dir=false)
Creates a new GribRecord by temporally interpolating between two time points.
zuchar id_grid
Grid identifier used by the originating center.
bool ok
Indicates record validity.
double GetInterpolatedValue(double px, double py, bool numericalInterpolation=true, bool dir=false) const
Get spatially interpolated value at exact lat/lon position.
zuchar GetIdCenter() const
Returns the originating center ID as defined by WMO (World Meteorological Organization).
int id
Unique identifier for this record.
bool hasBMS
Indicates presence of a bitmap section.
zuint level_value
Numeric value associated with level_type.
int GetPeriodP1() const
Returns the start of the period (P1) used for this record.
bool wave_data
Differentiates wave-related parameters (height, direction, period) from other meteorological data for...
int GetNi() const
Returns the number of points in the longitude (i) direction of the grid.
zuint GetLevelValue() const
Returns the numeric value associated with the level type.
zuint refyear
Components of the reference time for this forecast.
zuchar data_type
Parameter identifier as defined by GRIB tables.
double GetDj() const
Returns the grid spacing in latitude (j) direction in degrees.
time_t ref_date
Unix timestamp of model initialization time.
zuchar level_type
Vertical level type indicator.
bool known_data
Indicates whether the data type in this record is recognized by the parser.
int data_center_model
Identifies the numerical weather model that produced this data.
zuchar id_center
Originating center ID as defined by WMO common table C-1.
zuchar edition_number
GRIB edition number, indicating the version of the GRIB specification used.
double GetDi() const
Returns the grid spacing in longitude (i) direction in degrees.
zuchar GetIdGrid() const
Returns the grid definition template number.
zuchar time_range
Statistical processing indicator.
zuchar GetLevelType() const
Returns the type of vertical level for this grid's data.