38void GribV1Record::translateDataType() {
48 multiplyAllData(3600.0);
74 multiplyAllData(3600.0);
97 multiplyAllData(3600.0);
147 id_grid == 255 && tableVersion == 128) {
164 multiplyAllData(0.102);
198 multiplyAllData(1000.0);
202 tableVersion == 228) {
215 tableVersion == 140) {
236 multiplyAllData(3600.0);
265 multiplyAllData(100.0);
280 multiplyAllData(100.0);
324GribV1Record::GribV1Record(
ZUFILE* file,
int id_) {
332 long start = zu_tell(file);
343 unsigned int b_haveReadGRIB = 0;
345 for (
unsigned i = 0; i < 4; i++) {
346 if (zu_read(file, strgrib + i, 1) != 1) {
351 if (strgrib[0] !=
'G') {
352 if (strgrib[i] ==
'G') {
363 if (b_haveReadGRIB == 0) {
364 if (strncmp(strgrib,
"GRIB", 4) != 0)
373 if ((strgrib[0] == 0) && (strgrib[1] == 0) && (strgrib[2] == 0) &&
380 ok = readGribSection0_IS(file, b_haveReadGRIB);
382 ok = readGribSection1_PDS(file);
383 zu_seek(file, fileOffset1 + sectionSize1, SEEK_SET);
386 ok = readGribSection2_GDS(file);
387 zu_seek(file, fileOffset2 + sectionSize2, SEEK_SET);
390 ok = readGribSection3_BMS(file);
391 zu_seek(file, fileOffset3 + sectionSize3, SEEK_SET);
394 ok = readGribSection4_BDS(file);
395 zu_seek(file, fileOffset4 + sectionSize4, SEEK_SET);
398 ok = readGribSection5_ES(file);
401 zu_seek(file, seekStart + totalSize + (b_len_add_8 ? 8 : 0), SEEK_SET);
409 zu_seek(file, start, SEEK_SET);
416#pragma warning(disable : 4717)
419#pragma warning(default : 4717)
422GribV1Record::~GribV1Record() {}
425static zuint readPackedBits(zuchar* buf, zuint first, zuint nbBits) {
428 if (nbBits == 0 || nbBits > 31) {
433 zuint oct = first / 8;
434 zuint bit = first % 8;
436 zuint val = (buf[oct] << 24) + (buf[oct + 1] << 16) + (buf[oct + 2] << 8) +
439 val = val >> (32 - nbBits);
449bool GribV1Record::readGribSection0_IS(
ZUFILE* file,
450 unsigned int b_skip_initial_GRIB) {
452 fileOffset0 = zu_tell(file);
454 if (b_skip_initial_GRIB == 0) {
456 while ((zu_read(file, strgrib, 1) == 1) && (strgrib[0] !=
'G')) {
459 if (strgrib[0] !=
'G') {
464 }
else if (b_skip_initial_GRIB ==
468 if (b_skip_initial_GRIB == 0 ||
469 b_skip_initial_GRIB ==
471 if (zu_read(file, strgrib + 1, 3) != 3) {
481 if (strncmp(strgrib,
"GRIB", 4) != 0) {
491 seekStart = zu_tell(file) - 4;
492 totalSize = readInt3(file);
506bool GribV1Record::readGribSection1_PDS(
ZUFILE* file) {
507 fileOffset1 = zu_tell(file);
508 if (zu_read(file, data1, 28) != 28) {
513 sectionSize1 = makeInt3(data1[0], data1[1], data1[2]);
514 tableVersion = data1[3];
518 hasGDS = (data1[7] & 128) != 0;
519 hasBMS = (data1[7] & 64) != 0;
525 refyear = (data1[24] - 1) * 100 + data1[12];
526 refmonth = data1[13];
529 refminute = data1[16];
532 sprintf(str_ref_date,
"%04d-%02d-%02d %02d:%02d",
refyear, refmonth, refday,
536 period_p2 = data1[19];
544 decim = (int)(((((zuint)data1[26] & 0x7F) << 8) + (zuint)data1[27]) & 0x7FFF);
545 if (data1[26] & 0x80) decim *= -1;
546 decimalFactorD = pow(10.0, decim);
550 erreur(
"Record %d: GDS not found",
id);
553 if (decimalFactorD == 0) {
554 erreur(
"Record %d: decimalFactorD null",
id);
562bool GribV1Record::readGribSection2_GDS(
ZUFILE* file) {
563 if (!hasGDS)
return 0;
564 fileOffset2 = zu_tell(file);
565 sectionSize2 = readInt3(file);
568 grid_type = readChar(file);
573 erreur(
"Record %d: unknown grid type GDS(6) : %d",
id, grid_type);
579 La1 = readSignedInt3(file) / 1000.0;
580 Lo1 = readSignedInt3(file) / 1000.0;
581 resol_flags = readChar(file);
582 La2 = readSignedInt3(file) / 1000.0;
583 Lo2 = readSignedInt3(file) / 1000.0;
589 Di = readSignedInt2(file) / 1000.0;
590 Dj = readSignedInt2(file) / 1000.0;
592 while (
Lo1 >
Lo2 && Di > 0) {
595 has_di_dj = (resol_flags & 0x80) != 0;
596 is_earth_spheric = (resol_flags & 0x40) == 0;
597 is_ueast_vnorth = (resol_flags & 0x08) == 0;
599 scan_flags = readChar(file);
600 is_scan_i_positive = (scan_flags & 0x80) == 0;
601 is_scan_j_positive = (scan_flags & 0x40) != 0;
602 is_adjacent_i = (scan_flags & 0x20) == 0;
618 if (Ni <= 1 || Nj <= 1) {
619 erreur(
"Record %d: Ni=%d Nj=%d",
id, Ni, Nj);
622 Di = (
Lo2 -
Lo1) / (Ni - 1);
623 Dj = (La2 - La1) / (Nj - 1);
627 printf(
"==== GV1 \n");
628 printf(
"Lo1=%f Lo2=%f La1=%f La2=%f\n",
Lo1,
Lo2, La1, La2);
629 printf(
"Ni=%d Nj=%d\n", Ni, Nj);
630 printf(
"has_di_dj=%d Di,Dj=(%f %f)\n", has_di_dj, Di, Dj);
631 printf(
"hasBMS=%d\n",
hasBMS);
632 printf(
"is_scan_i_positive=%d is_scan_j_positive=%d is_adjacent_i=%d\n",
633 is_scan_i_positive, is_scan_j_positive, is_adjacent_i);
641bool GribV1Record::readGribSection3_BMS(
ZUFILE* file) {
642 fileOffset3 = zu_tell(file);
647 sectionSize3 = readInt3(file);
648 (void)readChar(file);
649 int bitMapFollows = readInt2(file);
651 if (bitMapFollows != 0) {
654 if (sectionSize3 <= 6) {
658 bms_size = sectionSize3 - 6;
659 bms_bits =
new zuchar[bms_size];
661 for (zuint i = 0; i < bms_size; i++) {
662 bms_bits[i] = readChar(file);
670bool GribV1Record::readGribSection4_BDS(
ZUFILE* file) {
671 fileOffset4 = zu_tell(file);
672 sectionSize4 = readInt3(file);
674 zuchar flags = readChar(file);
675 scaleFactorE = readSignedInt2(file);
676 refValue = readFloat4(file);
677 nbBitsInPack = readChar(file);
678 scaleFactorEpow2 = pow(2., scaleFactorE);
679 unusedBitsEndBDS = flags & 0x0F;
680 isGridData = (flags & 0x80) == 0;
681 isSimplePacking = (flags & 0x80) == 0;
682 isFloatValues = (flags & 0x80) == 0;
688 erreur(
"Record %d: need grid data",
id);
691 if (!isSimplePacking) {
692 erreur(
"Record %d: need simple packing",
id);
695 if (!isFloatValues) {
696 erreur(
"Record %d: need double values",
id);
704 if (sectionSize4 <= 11 || sectionSize4 > INT_MAX - 4) {
709 int datasize = sectionSize4 - 11;
711 new zuchar[datasize +
714 if (zu_read(file, buf, datasize) != datasize) {
715 erreur(
"Record %d: data read error",
id);
725 data =
new double[Ni * Nj];
731 for (j = 0; j < Nj; j++) {
732 for (i = 0; i < Ni; i++) {
736 if (!has_di_dj && !is_scan_j_positive) {
737 ind = (Nj-1 -j)*Ni+i;
746 if (HasValue(i, j)) {
747 x = readPackedBits(buf, startbit, nbBitsInPack);
748 data[ind] = (refValue + x * scaleFactorEpow2) / decimalFactorD;
749 startbit += nbBitsInPack;
752 data[ind] = GRIB_NOTDEF;
757 for (i = 0; i < Ni; i++) {
758 for (j = 0; j < Nj; j++) {
760 if (!has_di_dj && !is_scan_j_positive) {
761 ind = (Nj-1 -j)*Ni+i;
770 if (HasValue(i, j)) {
771 x = readPackedBits(buf, startbit, nbBitsInPack);
772 startbit += nbBitsInPack;
773 data[ind] = (refValue + x * scaleFactorEpow2) / decimalFactorD;
776 data[ind] = GRIB_NOTDEF;
789bool GribV1Record::readGribSection5_ES(
ZUFILE* file) {
791 if (zu_read(file, str, 4) != 4) {
796 if (strncmp(str,
"7777", 4) != 0) {
797 erreur(
"Final 7777 not read: %c%c%c%c", str[0], str[1], str[2], str[3]);
807double GribV1Record::readFloat4(
ZUFILE* file) {
809 if (zu_read(file, t, 4) != 4) {
816 int A = (zuint)t[0] & 0x7F;
817 int B = ((zuint)t[1] << 16) + ((zuint)t[2] << 8) + (zuint)t[3];
819 val = pow(2., -24) * B * pow(16., A - 64);
826zuchar GribV1Record::readChar(
ZUFILE* file) {
828 if (zu_read(file, &t, 1) != 1) {
836int GribV1Record::readSignedInt3(
ZUFILE* file) {
838 if (zu_read(file, t, 3) != 3) {
843 int val = (((zuint)t[0] & 0x7F) << 16) + ((zuint)t[1] << 8) + (zuint)t[2];
850int GribV1Record::readSignedInt2(
ZUFILE* file) {
852 if (zu_read(file, t, 2) != 2) {
857 int val = (((zuint)t[0] & 0x7F) << 8) + (zuint)t[1];
864zuint GribV1Record::readInt3(
ZUFILE* file) {
866 if (zu_read(file, t, 3) != 3) {
871 return ((zuint)t[0] << 16) + ((zuint)t[1] << 8) + (zuint)t[2];
874zuint GribV1Record::readInt2(
ZUFILE* file) {
876 if (zu_read(file, t, 2) != 2) {
881 return ((zuint)t[0] << 8) + (zuint)t[1];
884zuint GribV1Record::makeInt3(zuchar a, zuchar b, zuchar c) {
885 return ((zuint)a << 16) + ((zuint)b << 8) + (zuint)c;
888zuint GribV1Record::makeInt2(zuchar b, zuchar c) {
889 return ((zuint)b << 8) + (zuint)c;
892zuint GribV1Record::periodSeconds(zuchar
unit, zuchar P1, zuchar P2,
923 erreur(
"id=%d: unknown time unit in PDS b18=%d",
id,
unit);
927 grib_debug(
"id=%d: PDS unit %d (time range) b21=%d %d P1=%d P2=%d\n",
id,
928 unit, range, res, P1, P2);
951 dur = ((zuint)P1 << 8) + (zuint)P2;
954 erreur(
"id=%d: unknown time range in PDS b21=%d",
id, range);
A meteorological data grid from a GRIB (Gridded Binary) file.
bool eof
Signals when the end of the GRIB file has been reached during parsing.
zuint periodsec
Forecast period in seconds.
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.
double Lo2
Grid end coordinates.
zuint period_p1
Time range indicators for this forecast step.
double Lo1
Grid origin coordinates.
zuchar id_model
Model identifier within the originating center.
zuchar GetDataType() const
Returns the type of meteorological parameter stored in this grid.
zuchar id_grid
Grid identifier used by the originating center.
bool ok
Indicates record validity.
bool hasBMS
Indicates presence of a bitmap section.
zuint level_value
Numeric value associated with level_type.
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.
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.
zuchar time_range
Statistical processing indicator.
zuchar GetLevelType() const
Returns the type of vertical level for this grid's data.
GRIB Version 1 Record Implementation.