35void GribV1Record::translateDataType() {
45 multiplyAllData(3600.0);
71 multiplyAllData(3600.0);
94 multiplyAllData(3600.0);
144 idGrid == 255 && tableVersion == 128) {
161 multiplyAllData(0.102);
195 multiplyAllData(1000.0);
199 tableVersion == 228) {
212 tableVersion == 140) {
233 multiplyAllData(3600.0);
262 multiplyAllData(100.0);
277 multiplyAllData(100.0);
321GribV1Record::GribV1Record(
ZUFILE* file,
int id_) {
329 long start = zu_tell(file);
340 unsigned int b_haveReadGRIB = 0;
342 for (
unsigned i = 0; i < 4; i++) {
343 if (zu_read(file, strgrib + i, 1) != 1) {
348 if (strgrib[0] !=
'G') {
349 if (strgrib[i] ==
'G') {
360 if (b_haveReadGRIB == 0) {
361 if (strncmp(strgrib,
"GRIB", 4) != 0)
370 if ((strgrib[0] == 0) && (strgrib[1] == 0) && (strgrib[2] == 0) &&
377 ok = readGribSection0_IS(file, b_haveReadGRIB);
379 ok = readGribSection1_PDS(file);
380 zu_seek(file, fileOffset1 + sectionSize1, SEEK_SET);
383 ok = readGribSection2_GDS(file);
384 zu_seek(file, fileOffset2 + sectionSize2, SEEK_SET);
387 ok = readGribSection3_BMS(file);
388 zu_seek(file, fileOffset3 + sectionSize3, SEEK_SET);
391 ok = readGribSection4_BDS(file);
392 zu_seek(file, fileOffset4 + sectionSize4, SEEK_SET);
395 ok = readGribSection5_ES(file);
398 zu_seek(file, seekStart + totalSize + (b_len_add_8 ? 8 : 0), SEEK_SET);
406 zu_seek(file, start, SEEK_SET);
413#pragma warning(disable : 4717)
416#pragma warning(default : 4717)
419GribV1Record::~GribV1Record() {}
422static zuint readPackedBits(zuchar* buf, zuint first, zuint nbBits) {
425 if (nbBits == 0 || nbBits > 31) {
430 zuint oct = first / 8;
431 zuint bit = first % 8;
433 zuint val = (buf[oct] << 24) + (buf[oct + 1] << 16) + (buf[oct + 2] << 8) +
436 val = val >> (32 - nbBits);
446bool GribV1Record::readGribSection0_IS(
ZUFILE* file,
447 unsigned int b_skip_initial_GRIB) {
449 fileOffset0 = zu_tell(file);
451 if (b_skip_initial_GRIB == 0) {
453 while ((zu_read(file, strgrib, 1) == 1) && (strgrib[0] !=
'G')) {
456 if (strgrib[0] !=
'G') {
461 }
else if (b_skip_initial_GRIB ==
465 if (b_skip_initial_GRIB == 0 ||
466 b_skip_initial_GRIB ==
468 if (zu_read(file, strgrib + 1, 3) != 3) {
478 if (strncmp(strgrib,
"GRIB", 4) != 0) {
488 seekStart = zu_tell(file) - 4;
489 totalSize = readInt3(file);
503bool GribV1Record::readGribSection1_PDS(
ZUFILE* file) {
504 fileOffset1 = zu_tell(file);
505 if (zu_read(file, data1, 28) != 28) {
510 sectionSize1 = makeInt3(data1[0], data1[1], data1[2]);
511 tableVersion = data1[3];
515 hasGDS = (data1[7] & 128) != 0;
516 hasBMS = (data1[7] & 64) != 0;
522 refyear = (data1[24] - 1) * 100 + data1[12];
523 refmonth = data1[13];
526 refminute = data1[16];
528 refDate = makeDate(
refyear, refmonth, refday, refhour, refminute, 0);
529 sprintf(strRefDate,
"%04d-%02d-%02d %02d:%02d",
refyear, refmonth, refday,
533 periodP2 = data1[19];
540 decim = (int)(((((zuint)data1[26] & 0x7F) << 8) + (zuint)data1[27]) & 0x7FFF);
541 if (data1[26] & 0x80) decim *= -1;
542 decimalFactorD = pow(10.0, decim);
546 erreur(
"Record %d: GDS not found",
id);
549 if (decimalFactorD == 0) {
550 erreur(
"Record %d: decimalFactorD null",
id);
558bool GribV1Record::readGribSection2_GDS(
ZUFILE* file) {
559 if (!hasGDS)
return 0;
560 fileOffset2 = zu_tell(file);
561 sectionSize2 = readInt3(file);
564 gridType = readChar(file);
569 erreur(
"Record %d: unknown grid type GDS(6) : %d",
id, gridType);
575 La1 = readSignedInt3(file) / 1000.0;
576 Lo1 = readSignedInt3(file) / 1000.0;
577 resolFlags = readChar(file);
578 La2 = readSignedInt3(file) / 1000.0;
579 Lo2 = readSignedInt3(file) / 1000.0;
585 Di = readSignedInt2(file) / 1000.0;
586 Dj = readSignedInt2(file) / 1000.0;
588 while (
Lo1 >
Lo2 && Di > 0) {
591 hasDiDj = (resolFlags & 0x80) != 0;
592 isEarthSpheric = (resolFlags & 0x40) == 0;
593 isUeastVnorth = (resolFlags & 0x08) == 0;
595 scanFlags = readChar(file);
596 isScanIpositive = (scanFlags & 0x80) == 0;
597 isScanJpositive = (scanFlags & 0x40) != 0;
598 isAdjacentI = (scanFlags & 0x20) == 0;
614 if (Ni <= 1 || Nj <= 1) {
615 erreur(
"Record %d: Ni=%d Nj=%d",
id, Ni, Nj);
618 Di = (
Lo2 -
Lo1) / (Ni - 1);
619 Dj = (La2 - La1) / (Nj - 1);
623 printf(
"==== GV1 \n");
624 printf(
"Lo1=%f Lo2=%f La1=%f La2=%f\n",
Lo1,
Lo2, La1, La2);
625 printf(
"Ni=%d Nj=%d\n", Ni, Nj);
626 printf(
"hasDiDj=%d Di,Dj=(%f %f)\n", hasDiDj, Di, Dj);
627 printf(
"hasBMS=%d\n",
hasBMS);
628 printf(
"isScanIpositive=%d isScanJpositive=%d isAdjacentI=%d\n",
629 isScanIpositive, isScanJpositive, isAdjacentI);
637bool GribV1Record::readGribSection3_BMS(
ZUFILE* file) {
638 fileOffset3 = zu_tell(file);
643 sectionSize3 = readInt3(file);
644 (void)readChar(file);
645 int bitMapFollows = readInt2(file);
647 if (bitMapFollows != 0) {
650 if (sectionSize3 <= 6) {
654 BMSsize = sectionSize3 - 6;
655 BMSbits =
new zuchar[BMSsize];
657 for (zuint i = 0; i < BMSsize; i++) {
658 BMSbits[i] = readChar(file);
666bool GribV1Record::readGribSection4_BDS(
ZUFILE* file) {
667 fileOffset4 = zu_tell(file);
668 sectionSize4 = readInt3(file);
670 zuchar flags = readChar(file);
671 scaleFactorE = readSignedInt2(file);
672 refValue = readFloat4(file);
673 nbBitsInPack = readChar(file);
674 scaleFactorEpow2 = pow(2., scaleFactorE);
675 unusedBitsEndBDS = flags & 0x0F;
676 isGridData = (flags & 0x80) == 0;
677 isSimplePacking = (flags & 0x80) == 0;
678 isFloatValues = (flags & 0x80) == 0;
684 erreur(
"Record %d: need grid data",
id);
687 if (!isSimplePacking) {
688 erreur(
"Record %d: need simple packing",
id);
691 if (!isFloatValues) {
692 erreur(
"Record %d: need double values",
id);
700 if (sectionSize4 <= 11 || sectionSize4 > INT_MAX - 4) {
705 int datasize = sectionSize4 - 11;
707 new zuchar[datasize +
710 if (zu_read(file, buf, datasize) != datasize) {
711 erreur(
"Record %d: data read error",
id);
721 data =
new double[Ni * Nj];
727 for (j = 0; j < Nj; j++) {
728 for (i = 0; i < Ni; i++) {
732 if (!hasDiDj && !isScanJpositive) {
733 ind = (Nj-1 -j)*Ni+i;
742 if (hasValue(i, j)) {
743 x = readPackedBits(buf, startbit, nbBitsInPack);
744 data[ind] = (refValue + x * scaleFactorEpow2) / decimalFactorD;
745 startbit += nbBitsInPack;
748 data[ind] = GRIB_NOTDEF;
753 for (i = 0; i < Ni; i++) {
754 for (j = 0; j < Nj; j++) {
756 if (!hasDiDj && !isScanJpositive) {
757 ind = (Nj-1 -j)*Ni+i;
766 if (hasValue(i, j)) {
767 x = readPackedBits(buf, startbit, nbBitsInPack);
768 startbit += nbBitsInPack;
769 data[ind] = (refValue + x * scaleFactorEpow2) / decimalFactorD;
772 data[ind] = GRIB_NOTDEF;
785bool GribV1Record::readGribSection5_ES(
ZUFILE* file) {
787 if (zu_read(file, str, 4) != 4) {
792 if (strncmp(str,
"7777", 4) != 0) {
793 erreur(
"Final 7777 not read: %c%c%c%c", str[0], str[1], str[2], str[3]);
803double GribV1Record::readFloat4(
ZUFILE* file) {
805 if (zu_read(file, t, 4) != 4) {
812 int A = (zuint)t[0] & 0x7F;
813 int B = ((zuint)t[1] << 16) + ((zuint)t[2] << 8) + (zuint)t[3];
815 val = pow(2., -24) * B * pow(16., A - 64);
822zuchar GribV1Record::readChar(
ZUFILE* file) {
824 if (zu_read(file, &t, 1) != 1) {
832int GribV1Record::readSignedInt3(
ZUFILE* file) {
834 if (zu_read(file, t, 3) != 3) {
839 int val = (((zuint)t[0] & 0x7F) << 16) + ((zuint)t[1] << 8) + (zuint)t[2];
846int GribV1Record::readSignedInt2(
ZUFILE* file) {
848 if (zu_read(file, t, 2) != 2) {
853 int val = (((zuint)t[0] & 0x7F) << 8) + (zuint)t[1];
860zuint GribV1Record::readInt3(
ZUFILE* file) {
862 if (zu_read(file, t, 3) != 3) {
867 return ((zuint)t[0] << 16) + ((zuint)t[1] << 8) + (zuint)t[2];
870zuint GribV1Record::readInt2(
ZUFILE* file) {
872 if (zu_read(file, t, 2) != 2) {
877 return ((zuint)t[0] << 8) + (zuint)t[1];
880zuint GribV1Record::makeInt3(zuchar a, zuchar b, zuchar c) {
881 return ((zuint)a << 16) + ((zuint)b << 8) + (zuint)c;
884zuint GribV1Record::makeInt2(zuchar b, zuchar c) {
885 return ((zuint)b << 8) + (zuint)c;
888zuint GribV1Record::periodSeconds(zuchar
unit, zuchar P1, zuchar P2,
919 erreur(
"id=%d: unknown time unit in PDS b18=%d",
id,
unit);
923 grib_debug(
"id=%d: PDS unit %d (time range) b21=%d %d P1=%d P2=%d\n",
id,
924 unit, range, res, P1, P2);
947 dur = ((zuint)P1 << 8) + (zuint)P2;
950 erreur(
"id=%d: unknown time range in PDS b21=%d",
id, range);
GRIB Version 1 Record Implementation.
Represents a meteorological data grid from a GRIB (Gridded Binary) file.
zuchar getTimeRange() const
Returns the time range indicator that defines how P1 and P2 should be interpreted.
bool eof
Signals when the end of the GRIB file has been reached during parsing.
zuint periodsec
Forecast period in seconds.
zuchar dataType
Parameter identifier as defined by GRIB tables.
zuchar editionNumber
GRIB edition number, indicating the version of the GRIB specification used.
bool knownData
Indicates whether the data type in this record is recognized by the parser.
zuchar levelType
Vertical level type indicator.
double Lo2
Grid end coordinates.
double Lo1
Grid origin coordinates.
time_t curDate
Unix timestamp of when this forecast is valid.
zuchar timeRange
Statistical processing indicator.
bool IsDuplicated
Indicates if this record was created through copying rather than direct reading.
zuchar idCenter
Originating center ID as defined by WMO common table C-1.
bool ok
Indicates record validity.
zuchar idGrid
Grid identifier used by the originating center.
zuint periodP1
Time range indicators for this forecast step.
time_t refDate
Unix timestamp of model initialization time.
bool hasBMS
Indicates presence of a bitmap section.
int dataCenterModel
Identifies the numerical weather model that produced this data.
zuint refyear
Components of the reference time for this forecast.
zuint levelValue
Numeric value associated with levelType.
zuint getLevelValue() const
Returns the numeric value associated with the level type.
zuchar getLevelType() const
Returns the type of vertical level for this grid's data.
zuchar idModel
Model identifier within the originating center.
zuchar getDataType() const
Returns the type of meteorological parameter stored in this grid.