Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members  

GRIB.cpp

Go to the documentation of this file.
00001 //-----------------------------------------------------------------------------
00002 //
00003 //  File        : GRIB.cpp
00004 //  Description : GRIB File interface implementation
00005 //  Project     : LAMMA 2004
00006 //  Author      : Graziano Giuliani (LaMMA Regione Toscana)
00007 //  References  : http://www.wmo.ch/web/www/WDM/Guides/Guide-binary-2.html
00008 //  RCS ID      : $Id: GRIB.cpp,v 1.6 2004/09/10 09:51:36 ocean Exp $
00009 //
00010 //  This program is free software; you can redistribute it and/or modify
00011 //  it under the terms of the GNU General Public License as published by
00012 //  the Free Software Foundation; either version 2 of the License, or
00013 //  (at your option) any later version.
00014 //
00015 //  This program is distributed in the hope that it will be useful,
00016 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 //  GNU General Public License for more details.
00019 //
00020 //  You should have received a copy of the GNU General Public License
00021 //  along with this program; if not, write to the Free Software
00022 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023 //
00024 //-----------------------------------------------------------------------------
00025 
00026 #include <sys/types.h>
00027 #include <sys/stat.h>
00028 #include <sys/mman.h>
00029 #include <unistd.h>
00030 #include <fcntl.h>
00031 
00032 #include <Ebisuzaki.h>
00033 #include <GRIB.h>
00034 
00035 #include <iostream>
00036 #include <sstream>
00037 #include <iomanip>
00038 
00039 // ############################################################################
00040 // GRIB Time implementation
00041 // ############################################################################
00042 
00043 GRIB_TIME::GRIB_TIME( )
00044 {
00045   year = month = day = hour = minute = 0;
00046   p1 = p2 = p1p2 = naveraged = nmissing = 0;
00047   timeunit = GRIB_TIMEUNIT_UNKNOWN;
00048   timerange = GRIB_TIMERANGE_UNKNOWN;
00049   reftime = "2000-01-01 00:00:00 UTC";
00050   timestring = "Undefined time";
00051 }
00052 
00053 void GRIB_TIME::strref( )
00054 {
00055   std::stringstream s;
00056   s << std::setw(4) << std::setfill('0') << year << "-"
00057     << std::setw(2) << std::setfill('0') << month << "-"
00058     << std::setw(2) << std::setfill('0') << day << " "
00059     << std::setw(2) << std::setfill('0') << hour << ":"
00060     << std::setw(2) << std::setfill('0') << minute << ":00 UTC";
00061   reftime = s.str( );
00062   return;
00063 }
00064 
00065 void GRIB_TIME::strtime( )
00066 {
00067   std::stringstream s;
00068   char *unitstr = timeunitstr( );
00069   switch (timerange)
00070   {
00071     case GRIB_TIMERANGE_FORECAST_AT_REFTIME_PLUS_P1:
00072       if (p1 == 0)
00073         s << "Uninitialized analysis product or image for " << reftime;
00074       else
00075         s << "Forecast product valid for " << reftime
00076           << " + " << p1 << " " << unitstr;
00077       break;
00078     case GRIB_TIMERANGE_ANALYSIS_AT_REFTIME:
00079       s << "Initialized analysis product for " << reftime;
00080       break;
00081     case GRIB_TIMERANGE_VALID_IN_REFTIME_PLUS_P1_REFTIME_PLUS_P2:
00082       s << "Product valid between " << reftime
00083         << " + " << p1 << " " << unitstr << " and" << std::endl
00084         << "                      " << reftime
00085         << " + " << p2 << " " << unitstr;
00086       break;
00087     case GRIB_TIMERANGE_AVERAGE_IN_REFTIME_PLUS_P1_REFTIME_PLUS_P2:
00088       s << "Average from " << reftime
00089         << " + " << p1 << " " << unitstr << " and" << std::endl
00090         << "             " << reftime << " + " << p2 << " " << unitstr;
00091       break;
00092     case GRIB_TIMERANGE_ACCUMULATED_INTERVAL_REFTIME_PLUS_P1_REFTIME_PLUS_P2:
00093       s << "Accumulated from " << reftime
00094         << " + " << p1 << " " << unitstr << " and" << std::endl
00095         << "                 " << reftime << " + " << p2 << " " << unitstr;
00096       break;
00097     case GRIB_TIMERANGE_DIFFERENCE_REFTIME_PLUS_P2_REFTIME_PLUS_P1:
00098       s << "Difference between product at " << reftime
00099         << " + " << p1 << " " << unitstr << " and" << std::endl
00100         << "                   product at "
00101         << reftime << " + " << p2 << " " << unitstr;
00102       break;
00103     case GRIB_TIMERANGE_AVERAGE_IN_REFTIME_MINUS_P1_REFTIME_MINUS_P2:
00104       s << "Average from " << reftime
00105         << " - " << p1 << " " << unitstr << " and" << std::endl
00106         << "             " << reftime << " - " << p2 << " " << unitstr;
00107       break;
00108     case GRIB_TIMERANGE_AVERAGE_IN_REFTIME_MINUS_P1_REFTIME_PLUS_P2: 
00109       s << "Average from " << reftime
00110         << " - " << p1 << " " << unitstr << " and" << std::endl
00111         << "             " << reftime << " + " << p2 << " " << unitstr;
00112       break;
00113     case GRIB_TIMERANGE_VALID_AT_REFTIME_PLUS_P1P2:
00114       s << "Forecast product valid for " << reftime
00115         << " + " << p1p2 << " " << unitstr;
00116       break;
00117     case GRIB_TIMERANGE_CLIMATOLOGICAL_MEAN_OVER_MULTIPLE_YEARS_FOR_P2:
00118       s << "Climatological mean of " << naveraged << "/" << nmissing
00119         << " years from " 
00120         << reftime << " for " << p2 << " " << unitstr;
00121       break;
00122     case GRIB_TIMERANGE_AVERAGE_OVER_FORECAST_OF_PERIOD_P1_REFTIME_PERIOD_P2:
00123       s << "Average of " << naveraged << "/" << nmissing;
00124       if (p1 == 0) s << " initialized analyses";
00125       else s << " forecasts with period " << p1 << " " << unitstr; 
00126       s << std::endl << "starting at " << reftime << " at intervals of " << p2
00127         << " " << unitstr;
00128       break;
00129     case GRIB_TIMERANGE_ACCUMULATED_OVER_FORECAST_PERIOD_P1_REFTIME_PERIOD_P2:
00130       s << "Accumulated of " << naveraged << "/" << nmissing;
00131       if (p1 == 0) s << " initialized analyses";
00132       else s << " forecasts with period " << p1 << " " << unitstr; 
00133       s << std::endl << "starting at " << reftime << " at intervals of " << p2
00134         << " " << unitstr;
00135       break;
00136     case GRIB_TIMERANGE_AVERAGE_OVER_FORECAST_OF_PERIOD_P1_AT_INTERVALS_P2:
00137       s << "Average of " << naveraged << "/" << nmissing
00138         << " forecasts at " << reftime
00139         << ", first with period " << p1 << " " << unitstr << std::endl
00140         << "and the other following at intervals of " << p2 << " " << unitstr; 
00141       break;
00142     case GRIB_TIMERANGE_ACCUMULATION_OVER_FORECAST_PERIOD_P1_AT_INTERVALS_P2:
00143       s << "Accumulation of " << naveraged << "/" << nmissing
00144         << " forecasts at " << reftime
00145         << ", first with period " << p1 << " " << unitstr << std::endl
00146         << "and the other following at intervals of " << p2 << " " << unitstr; 
00147       break;
00148     case GRIB_TIMERANGE_AVERAGE_OVER_FORECAST_FIRST_P1_OTHER_P2_REDUCED:
00149       s << "Average of " << naveraged << "/" << nmissing
00150         << " forecasts at " << reftime
00151         << ", first with" << std::endl << "period " << p1 << " " << unitstr
00152         << " and the other with period reduced by " << p2 << " " << unitstr; 
00153       break;
00154     case GRIB_TIMERANGE_VARIANCE_OF_ANALYSES_WITH_REFERENCE_TIME_INTERVALS_P2:
00155       s << "Temporal variance or covariance of " << naveraged
00156         << "/" << nmissing
00157         << " initialized analyses," << std::endl << "starting at "
00158         << reftime << " with intervals of " << p2 << " " << unitstr;
00159       break;
00160     case GRIB_TIMERANGE_STDDEV_OF_FORECASTS_FIRST_P1_OTHER_P2_REDUCED:
00161       s << "Standard deviation of " << naveraged << "/" << nmissing
00162         << " forecasts at "
00163         << reftime << std::endl << "the first with period " << p1
00164         << " " << unitstr << " and the other following at "
00165         << p2 << " " << unitstr << " intervals";
00166       break;
00167     case GRIB_TIMERANGE_AVERAGE_OVER_ANALYSES_AT_INTERVALS_OF_P2:
00168       s << "Average of " << naveraged << "/" << nmissing
00169         << " uninitialized analyses "
00170         << "starting at " << reftime << "," << std::endl
00171         << "at intervals of " << p2 << " " << unitstr;
00172       break;
00173     case GRIB_TIMERANGE_ACCUMULATION_OVER_ANALYSES_AT_INTERVALS_OF_P2:
00174       s << "Accumulation of " << naveraged << "/" << nmissing
00175         << " uninitialized analyses "
00176         << "starting at " << reftime << "," << std::endl
00177         << "at intervals of " << p2 << " " << unitstr;
00178       break;
00179     case GRIB_TIMERANGE_STDDEV_OF_FORECASTS_RESPECT_TO_AVERAGE_OF_TENDENCY:
00180       s << "Standard deviation of " << naveraged << "/" << nmissing
00181         << " forecasts at "
00182         << reftime << ", with respect" << std::endl
00183         << "to time average of time tendency." << std::endl
00184         << "First forecast has period " << p1 << " " << unitstr
00185         << ", the other follow at intervals of " << p2 << " " << unitstr;
00186       break;
00187     case GRIB_TIMERANGE_AVERAGE_OF_DAILY_FORECAST_ACCUMULATIONS:
00188       s << "Average of " << naveraged << "/" << nmissing
00189         << " daily forecast accumulation"
00190         << " for " << reftime << std::endl << "from " << p1 << " " << unitstr
00191         << " to " << p2 << " " << unitstr << " with 1 day period.";
00192       break;
00193     case GRIB_TIMERANGE_AVERAGE_OF_SUCCESSIVE_FORECAST_ACCUMULATIONS:
00194       s << "Average of " << naveraged << "/" << nmissing
00195         << " successive forecast accumulation"
00196         << " for " << reftime << std::endl << "from " << p1 << " " << unitstr
00197         << " to " << p2 << " " << unitstr << " with " << (p2-p1) << " "
00198         << unitstr << " period";
00199       break;
00200     case GRIB_TIMERANGE_AVERAGE_OF_DAILY_FORECAST_AVERAGES:
00201       s << "Average of " << naveraged << "/" << nmissing
00202         << " daily forecast averages"
00203         << " for " << reftime << std::endl << "from " << p1 << " " << unitstr
00204         << " to " << p2 << " " << unitstr << " with 1 day period.";
00205       break;
00206     case GRIB_TIMERANGE_AVERAGE_OF_SUCCESSIVE_FORECAST_AVERAGES:
00207       s << "Average of " << naveraged << "/" << nmissing
00208         << " successive forecast averages"
00209         << " for " << reftime << std::endl << "from " << p1 << " " << unitstr
00210         << " to " << p2 << " " << unitstr << " with " << (p2-p1) << " "
00211         << unitstr << " period";
00212     default:
00213       std::cerr << "Unknown time range indicator: " << timerange << std::endl;
00214       break;
00215   }
00216   timestring = s.str( );
00217   return;
00218 }
00219 
00220 void GRIB_TIME::Decode(unsigned char *pds)
00221 {
00222   year = PDS_Year4(pds);
00223   month = PDS_Month(pds);
00224   day = PDS_Day(pds);
00225   hour = PDS_Hour(pds);
00226   minute = PDS_Minute(pds);
00227 
00228   timeunit = (t_enum_GRIB_TIMEUNIT) PDS_ForecastTimeUnit(pds);
00229   p1 = PDS_P1(pds);
00230   p2 = PDS_P2(pds);
00231   p1p2 = PDS_P1P2(pds);
00232   timerange = (t_enum_GRIB_TIMERANGE) PDS_TimeRange(pds);
00233   naveraged = PDS_NumAve(pds);
00234   nmissing = PDS_NumMissing(pds);
00235 
00236   strref( );
00237   strtime( );
00238 
00239   return;
00240 }
00241 
00242 unsigned char *GRIB_TIME::Encode( )
00243 {
00244   static unsigned char time_encoded[13];
00245   time_encoded[0]  = (year%100);      // pds 13
00246   time_encoded[1]  = month;           // pds 14
00247   time_encoded[2]  = day;             // pds 15
00248   time_encoded[3]  = hour;            // pds 16
00249   time_encoded[4]  = minute;          // pds 17
00250   time_encoded[5]  = timeunit;        // pds 18
00251   time_encoded[6]  = p1;              // pds 19
00252   time_encoded[7]  = p2;              // pds 20
00253   time_encoded[8]  = timerange;       // pds 21
00254   time_encoded[9]  = (naveraged/256); // pds 22
00255   time_encoded[10] = (naveraged%256); // pds 23
00256   time_encoded[11] = nmissing;        // pds 24
00257   time_encoded[12] = (year/100)+1;    // pds 25
00258   return time_encoded;
00259 }
00260 
00261 void GRIB_TIME::set(int year, int month, int day, int hour, int minute,
00262                     t_enum_GRIB_TIMEUNIT tu, t_enum_GRIB_TIMERANGE tr,
00263                     int time1, int time2, int nave, int nmiss)
00264 {
00265   set_referencetime(year, month, day, hour, minute);
00266   set_time(tu, tr, time1, time2, nave, nmiss);
00267   return;
00268 }
00269 
00270 void GRIB_TIME::set_analysis( )
00271 {
00272   timeunit = GRIB_TIMEUNIT_HOUR;
00273   timerange = GRIB_TIMERANGE_ANALYSIS_AT_REFTIME;
00274   p1 = p2 = p1p2 = naveraged = nmissing = 0;
00275   strtime( );
00276 }
00277 
00278 void GRIB_TIME::set_forecast_hour(int hforecast)
00279 {
00280   if (hforecast < 0)
00281   {
00282     std::cerr << "Negative or zero lenght forecast ????" << std::endl;
00283     throw;
00284   }
00285 
00286   timeunit = GRIB_TIMEUNIT_HOUR;
00287   timerange = GRIB_TIMERANGE_FORECAST_AT_REFTIME_PLUS_P1;
00288   p1 = hforecast;
00289   p2 = p1p2 = 0;
00290   if (hforecast > 255)
00291   {
00292     timerange = GRIB_TIMERANGE_VALID_AT_REFTIME_PLUS_P1P2;
00293     p1p2 = hforecast;
00294     p1 = p1p2/256;
00295     p2 = p1p2%256;
00296   }
00297   naveraged = nmissing = 0;
00298   strtime( );
00299 }
00300 
00301 void GRIB_TIME::set_referencetime(int year, int month, int day,
00302                                   int hour, int minute)
00303 {
00304   this->year = year;
00305   this->month = month;
00306   this->day = day;
00307   this->hour = hour;
00308   this->minute = minute;
00309   strref( );
00310   return;
00311 }
00312 
00313 void GRIB_TIME::set_time(t_enum_GRIB_TIMEUNIT tu, t_enum_GRIB_TIMERANGE tr,
00314                          int time)
00315 {
00316   this->set_time(tu, tr, time, 0, 0, 0);
00317   strtime( );
00318   return;
00319 }
00320 
00321 void GRIB_TIME::set_time(t_enum_GRIB_TIMEUNIT tu, t_enum_GRIB_TIMERANGE tr,
00322                          int time1, int time2)
00323 {
00324   this->set_time(tu, tr, time1, time2, 0, 0);
00325   strtime( );
00326   return;
00327 }
00328 
00329 void GRIB_TIME::set_time(t_enum_GRIB_TIMEUNIT tu, t_enum_GRIB_TIMERANGE tr,
00330                          int time1, int time2, int nave, int nmiss)
00331 {
00332   timeunit = tu;
00333   timerange = tr;
00334   switch (timerange)
00335   {
00336     case GRIB_TIMERANGE_FORECAST_AT_REFTIME_PLUS_P1:
00337       p1 = time1;
00338       break;
00339     case GRIB_TIMERANGE_ANALYSIS_AT_REFTIME:
00340       break;
00341     case GRIB_TIMERANGE_AVERAGE_IN_REFTIME_PLUS_P1_REFTIME_PLUS_P2:
00342     case GRIB_TIMERANGE_ACCUMULATED_INTERVAL_REFTIME_PLUS_P1_REFTIME_PLUS_P2:
00343     case GRIB_TIMERANGE_DIFFERENCE_REFTIME_PLUS_P2_REFTIME_PLUS_P1:
00344     case GRIB_TIMERANGE_AVERAGE_IN_REFTIME_MINUS_P1_REFTIME_MINUS_P2:
00345     case GRIB_TIMERANGE_AVERAGE_IN_REFTIME_MINUS_P1_REFTIME_PLUS_P2: 
00346       p1 = time1;
00347       p2 = time2;
00348       break;
00349     case GRIB_TIMERANGE_VALID_AT_REFTIME_PLUS_P1P2:
00350       p1 = time1/256;
00351       p2 = time1%256;
00352       p1p2 = time1;
00353       break;
00354     case GRIB_TIMERANGE_CLIMATOLOGICAL_MEAN_OVER_MULTIPLE_YEARS_FOR_P2:
00355     case GRIB_TIMERANGE_AVERAGE_OVER_FORECAST_OF_PERIOD_P1_REFTIME_PERIOD_P2:
00356     case GRIB_TIMERANGE_ACCUMULATED_OVER_FORECAST_PERIOD_P1_REFTIME_PERIOD_P2:
00357     case GRIB_TIMERANGE_AVERAGE_OVER_FORECAST_OF_PERIOD_P1_AT_INTERVALS_P2:
00358     case GRIB_TIMERANGE_ACCUMULATION_OVER_FORECAST_PERIOD_P1_AT_INTERVALS_P2:
00359     case GRIB_TIMERANGE_AVERAGE_OVER_FORECAST_FIRST_P1_OTHER_P2_REDUCED:
00360     case GRIB_TIMERANGE_STDDEV_OF_FORECASTS_FIRST_P1_OTHER_P2_REDUCED:
00361     case GRIB_TIMERANGE_STDDEV_OF_FORECASTS_RESPECT_TO_AVERAGE_OF_TENDENCY:
00362     case GRIB_TIMERANGE_AVERAGE_OF_DAILY_FORECAST_ACCUMULATIONS:
00363     case GRIB_TIMERANGE_AVERAGE_OF_DAILY_FORECAST_AVERAGES:
00364     case GRIB_TIMERANGE_AVERAGE_OF_SUCCESSIVE_FORECAST_ACCUMULATIONS:
00365     case GRIB_TIMERANGE_AVERAGE_OF_SUCCESSIVE_FORECAST_AVERAGES:
00366       p1 = time1;
00367       p2 = time2;
00368       naveraged = nave;
00369       nmissing = nmiss;
00370       break;
00371     case GRIB_TIMERANGE_VARIANCE_OF_ANALYSES_WITH_REFERENCE_TIME_INTERVALS_P2:
00372     case GRIB_TIMERANGE_AVERAGE_OVER_ANALYSES_AT_INTERVALS_OF_P2:
00373     case GRIB_TIMERANGE_ACCUMULATION_OVER_ANALYSES_AT_INTERVALS_OF_P2:
00374       p1 = 0;
00375       p2 = time2;
00376       naveraged = nave;
00377       nmissing = nmiss;
00378       break;
00379     default:
00380       std::cerr << "Unknown time range indicator: " << timerange << std::endl;
00381       break;
00382   }
00383   strtime( );
00384   return;
00385 }
00386 
00387 char *GRIB_TIME::timeunitstr( )
00388 {
00389   switch (timeunit)
00390   {
00391     case GRIB_TIMEUNIT_MINUTE:
00392       return "minute";
00393       break;
00394     case GRIB_TIMEUNIT_HOUR:
00395       return "hour";
00396       break;
00397     case GRIB_TIMEUNIT_DAY:
00398       return "day";
00399       break;
00400     case GRIB_TIMEUNIT_MONTH:
00401       return "month";
00402       break;
00403     case GRIB_TIMEUNIT_YEAR:
00404       return "year";
00405       break;
00406     case GRIB_TIMEUNIT_DECADE:
00407       return "decade";
00408       break;
00409     case GRIB_TIMEUNIT_NORMAL:
00410       return "normal";
00411       break;
00412     case GRIB_TIMEUNIT_CENTURY:
00413       return "century";
00414       break;
00415     case GRIB_TIMEUNIT_HOURS3:
00416       return "x3 hours";
00417       break;
00418     case GRIB_TIMEUNIT_HOURS6:
00419       return "x6 hours";
00420       break;
00421     case GRIB_TIMEUNIT_HOURS12:
00422       return "x12 hours";
00423       break;
00424     case GRIB_TIMEUNIT_SECOND:
00425       return "second";
00426       break;
00427     default:
00428       return "unknown unit";
00429       break;
00430   }
00431 }
00432 
00433 time_t GRIB_TIME::ForecastSeconds( )
00434 {
00435   time_t rincr;
00436   int dtime = p1;
00437 
00438   if (timerange == GRIB_TIMERANGE_VALID_AT_REFTIME_PLUS_P1P2)
00439     dtime = p1p2;
00440   if (timerange > GRIB_TIMERANGE_ANALYSIS_AT_REFTIME &&
00441       timerange < GRIB_TIMERANGE_AVERAGE_IN_REFTIME_MINUS_P1_REFTIME_MINUS_P2)
00442     dtime = p2;
00443 
00444   if (timeunit == GRIB_TIMEUNIT_MINUTE)
00445     rincr = dtime * 60;
00446   else if (timeunit == GRIB_TIMEUNIT_HOUR)
00447     rincr = dtime * 3600;
00448   else if (timeunit == GRIB_TIMEUNIT_DAY)
00449     rincr = dtime * 86400;
00450   else if (timeunit == GRIB_TIMEUNIT_MONTH)
00451     rincr = dtime * 2592000;
00452   else if (timeunit == GRIB_TIMEUNIT_HOURS3)
00453     rincr = dtime * 10800;
00454   else if (timeunit == GRIB_TIMEUNIT_HOURS6)
00455     rincr = dtime * 21600;
00456   else if (timeunit == GRIB_TIMEUNIT_HOURS12)
00457     rincr = dtime * 43200;
00458   else if (timeunit == GRIB_TIMEUNIT_SECOND)
00459     rincr = dtime;
00460   else
00461     rincr = 0;
00462   return rincr;
00463 }
00464 
00465 std::string GRIB_TIME::Reftime( ) { return reftime; }
00466 std::string GRIB_TIME::TimeString( ) { return timestring; }
00467 
00468 std::string GRIB_TIME::Reftime2000( )
00469 {
00470   std::stringstream s;
00471   s << "2000-01-01 00:00:00 UTC";
00472   return s.str( );
00473 }
00474 
00475 time_t GRIB_TIME::ForecastSeconds2000( )
00476 {
00477   struct tm itm;
00478   time_t ttm;
00479   const time_t s_epoch_2000 = 946684800;
00480 
00481   memset(&itm, 0, sizeof(struct tm));
00482   itm.tm_year = year - 1900;
00483   itm.tm_mon  = month - 1;
00484   itm.tm_mday = day;
00485   itm.tm_hour = hour;
00486   itm.tm_min  = minute;
00487 
00488   tzset( );
00489   ttm = mktime(&itm) + ForecastSeconds( ) - timezone - s_epoch_2000;
00490   return ttm;
00491 }
00492 
00493 std::string GRIB_TIME::ValidTime( )
00494 {
00495   struct tm itm, *xtm;
00496   time_t ttm;
00497 
00498   memset(&itm, 0, sizeof(struct tm));
00499   itm.tm_year = year - 1900;
00500   itm.tm_mon  = month - 1;
00501   itm.tm_mday = day;
00502   itm.tm_hour = hour;
00503   itm.tm_min  = minute;
00504 
00505   tzset( );
00506   ttm = mktime(&itm) + ForecastSeconds( ) - timezone;
00507   xtm = gmtime(&ttm);
00508   
00509   char temp[32];
00510 
00511   strftime(temp, 32, "%Y-%m-%d %H:%M:00 UTC", xtm);
00512   std::string retval = temp;
00513   return retval;
00514 }
00515 
00516 std::ostream& operator<< ( std::ostream& os, GRIB_TIME &t )
00517 {
00518   os << t.timestring;
00519   return os;
00520 }
00521 
00522 // ############################################################################
00523 // GRIB Level implementation
00524 // ############################################################################
00525 
00526 GRIB_LEVEL::GRIB_LEVEL( )
00527 {
00528   type = GRIB_LEVEL_UNKNOWN;
00529   lv1 = 0.0;
00530   lv2 = 0.0;
00531 }
00532 
00533 void GRIB_LEVEL::set(t_enum_GRIB_LEVELS type)
00534 {
00535   this->set(type, 0.0, 0.0);
00536   return;
00537 }
00538 
00539 void GRIB_LEVEL::set(t_enum_GRIB_LEVELS type, float lev)
00540 {
00541   this->set(type, lev, 0.0);
00542   return;
00543 }
00544 
00545 void GRIB_LEVEL::set(t_enum_GRIB_LEVELS type, float lev1, float lev2)
00546 {
00547   lv1 = 0.0;
00548   lv2 = 0.0;
00549 
00550   this->type = type;
00551   switch (type)
00552   {
00553     case GRIB_LEVEL_SURFACE:
00554     case GRIB_LEVEL_CLOUD_BASE:
00555     case GRIB_LEVEL_CLOUD_TOP:
00556     case GRIB_LEVEL_ISOTHERM_0_DEG:
00557     case GRIB_LEVEL_ADIABATIC_CONDENSATION_LIFTED_FROM_SURFACE:
00558     case GRIB_LEVEL_MAXIMUM_WIND:
00559     case GRIB_LEVEL_TROPOPAUSE:
00560     case GRIB_LEVEL_NOMINAL_ATMOSPHERE_TOP:
00561     case GRIB_LEVEL_ENTIRE_ATMOSPHERE:
00562     case GRIB_LEVEL_ENTIRE_OCEAN:
00563     case GRIB_LEVEL_MEAN_SEA_LEVEL:
00564       break;
00565     case GRIB_LEVEL_ISOBARIC_mb:
00566     case GRIB_LEVEL_ALTITUDE_ABOVE_MSL_m:
00567     case GRIB_LEVEL_HEIGHT_ABOVE_GROUND_m:
00568     case GRIB_LEVEL_HYBRID:
00569     case GRIB_LEVEL_DEPTH_BELOW_SURFACE_cm:
00570     case GRIB_LEVEL_ISENTROPIC_K:
00571     case GRIB_LEVEL_PRESSURE_DIFFERENCE_FROM_GROUND_mb:
00572     case GRIB_LEVEL_POTENTIAL_VORTICITY_SURFACE_PV_UNITS:
00573     case GRIB_LEVEL_ISOBARIC_Pa:
00574     case GRIB_LEVEL_DEPTH_BELOW_SEA_m:
00575     case GRIB_LEVEL_HEIGHT_ABOVE_GROUND_HIGH_PRECISION_cm:
00576     case GRIB_LEVEL_ISOTHERMAL_K:
00577     case GRIB_LEVEL_SIGMA:
00578     case GRIB_LEVEL_ETA:
00579       lv1 = lev1;
00580       break;
00581     case GRIB_LEVEL_LAYER_HYBRID:
00582     case GRIB_LEVEL_LAYER_DEPTH_BELOW_SURFACE_cm:
00583     case GRIB_LEVEL_LAYER_PRESSURE_DIFFERENCE_FROM_GROUND_mb:
00584     case GRIB_LEVEL_LAYER_ISOBARIC_mb:
00585     case GRIB_LEVEL_LAYER_ALTITUDE_ABOVE_MSL_m:
00586     case GRIB_LEVEL_LAYER_HEIGHT_ABOVE_GROUND_m:
00587     case GRIB_LEVEL_LAYER_SIGMA:
00588     case GRIB_LEVEL_LAYER_ETA:
00589     case GRIB_LEVEL_LAYER_ISENTROPIC_K:
00590     case GRIB_LEVEL_LAYER_ISOBARIC_HIGH_PRECISION_mb:
00591     case GRIB_LEVEL_LAYER_SIGMA_HIGH_PRECISION:
00592     case GRIB_LEVEL_LAYER_ISOBARIC_MIXED_PRECISION_mb:
00593       lv1 = lev1;
00594       lv2 = lev2;
00595       break;
00596     default:
00597       std::cerr << "Unknown Level is used !!!!" << std::endl;
00598   }
00599   return;
00600 }
00601 
00602 int GRIB_LEVEL::Encode( )
00603 {
00604   int retval = 0;
00605   switch (type)
00606   {
00607     case GRIB_LEVEL_SURFACE:
00608     case GRIB_LEVEL_CLOUD_BASE:
00609     case GRIB_LEVEL_CLOUD_TOP:
00610     case GRIB_LEVEL_ISOTHERM_0_DEG:
00611     case GRIB_LEVEL_ADIABATIC_CONDENSATION_LIFTED_FROM_SURFACE:
00612     case GRIB_LEVEL_MAXIMUM_WIND:
00613     case GRIB_LEVEL_TROPOPAUSE:
00614     case GRIB_LEVEL_NOMINAL_ATMOSPHERE_TOP:
00615     case GRIB_LEVEL_ENTIRE_ATMOSPHERE:
00616     case GRIB_LEVEL_ENTIRE_OCEAN:
00617     case GRIB_LEVEL_MEAN_SEA_LEVEL:
00618       break;
00619     case GRIB_LEVEL_ISOBARIC_mb:
00620     case GRIB_LEVEL_ALTITUDE_ABOVE_MSL_m:
00621     case GRIB_LEVEL_HEIGHT_ABOVE_GROUND_m:
00622     case GRIB_LEVEL_HYBRID:
00623     case GRIB_LEVEL_DEPTH_BELOW_SURFACE_cm:
00624     case GRIB_LEVEL_ISENTROPIC_K:
00625     case GRIB_LEVEL_PRESSURE_DIFFERENCE_FROM_GROUND_mb:
00626     case GRIB_LEVEL_POTENTIAL_VORTICITY_SURFACE_PV_UNITS:
00627     case GRIB_LEVEL_ISOBARIC_Pa:
00628     case GRIB_LEVEL_DEPTH_BELOW_SEA_m:
00629     case GRIB_LEVEL_HEIGHT_ABOVE_GROUND_HIGH_PRECISION_cm:
00630       retval = (int) lv1;
00631       break;
00632     case GRIB_LEVEL_ISOTHERMAL_K:
00633       retval = (int) (lv1*100.0);
00634       break;
00635     case GRIB_LEVEL_SIGMA:
00636     case GRIB_LEVEL_ETA:
00637       retval = (int) (lv1*10000.0);
00638       break;
00639     case GRIB_LEVEL_LAYER_HYBRID:
00640     case GRIB_LEVEL_LAYER_DEPTH_BELOW_SURFACE_cm:
00641     case GRIB_LEVEL_LAYER_PRESSURE_DIFFERENCE_FROM_GROUND_mb:
00642       retval = ((int) lv1) << 8 + ((int) lv2);
00643       break;
00644     case GRIB_LEVEL_LAYER_ISOBARIC_mb:
00645       retval = ((int) (lv1/10.0)) << 8 + ((int) (lv2/10.0));
00646       break;
00647     case GRIB_LEVEL_LAYER_ALTITUDE_ABOVE_MSL_m:
00648     case GRIB_LEVEL_LAYER_HEIGHT_ABOVE_GROUND_m:
00649       retval = ((int) (lv1/100.0)) << 8 + ((int) (lv2/100.0));
00650       break;
00651     case GRIB_LEVEL_LAYER_SIGMA:
00652     case GRIB_LEVEL_LAYER_ETA:
00653       retval = ((int) (lv1*100.0)) << 8 + ((int) (lv2*100.0));
00654       break;
00655     case GRIB_LEVEL_LAYER_ISENTROPIC_K:
00656       retval = ((int) (475-lv1)) << 8 + ((int) (475-lv2));
00657       break;
00658     case GRIB_LEVEL_LAYER_ISOBARIC_HIGH_PRECISION_mb:
00659       retval = ((int) (1100-lv1)) << 8 + ((int) (1100-lv2));
00660       break;
00661     case GRIB_LEVEL_LAYER_SIGMA_HIGH_PRECISION:
00662       retval = ((int) (1000*lv1)) << 8 + ((int) (1000*lv2));
00663       break;
00664     case GRIB_LEVEL_LAYER_ISOBARIC_MIXED_PRECISION_mb:
00665       retval = ((int) lv1) << 8 + ((int) (1100-lv2));
00666       break;
00667     default:
00668       std::cerr << "Unknown Level is used !!!!" << std::endl;
00669   }
00670   return retval;
00671 }
00672 
00673 void GRIB_LEVEL::Decode(unsigned char *pds)
00674 {
00675   this->type = (t_enum_GRIB_LEVELS) PDS_KPDS6(pds);
00676 
00677   int lev = PDS_KPDS7(pds);
00678   int o11 = lev / 256;
00679   int o12 = lev % 256;
00680 
00681   lv1 = 0.0;
00682   lv2 = 0.0;
00683 
00684   switch (type)
00685   {
00686     case GRIB_LEVEL_SURFACE:
00687     case GRIB_LEVEL_CLOUD_BASE:
00688     case GRIB_LEVEL_CLOUD_TOP:
00689     case GRIB_LEVEL_ISOTHERM_0_DEG:
00690     case GRIB_LEVEL_ADIABATIC_CONDENSATION_LIFTED_FROM_SURFACE:
00691     case GRIB_LEVEL_MAXIMUM_WIND:
00692     case GRIB_LEVEL_TROPOPAUSE:
00693     case GRIB_LEVEL_NOMINAL_ATMOSPHERE_TOP:
00694     case GRIB_LEVEL_ENTIRE_ATMOSPHERE:
00695     case GRIB_LEVEL_ENTIRE_OCEAN:
00696     case GRIB_LEVEL_MEAN_SEA_LEVEL:
00697       break;
00698     case GRIB_LEVEL_ISOBARIC_mb:
00699     case GRIB_LEVEL_ALTITUDE_ABOVE_MSL_m:
00700     case GRIB_LEVEL_HEIGHT_ABOVE_GROUND_m:
00701     case GRIB_LEVEL_HYBRID:
00702     case GRIB_LEVEL_DEPTH_BELOW_SURFACE_cm:
00703     case GRIB_LEVEL_ISENTROPIC_K:
00704     case GRIB_LEVEL_PRESSURE_DIFFERENCE_FROM_GROUND_mb:
00705     case GRIB_LEVEL_POTENTIAL_VORTICITY_SURFACE_PV_UNITS:
00706     case GRIB_LEVEL_ISOBARIC_Pa:
00707     case GRIB_LEVEL_DEPTH_BELOW_SEA_m:
00708     case GRIB_LEVEL_HEIGHT_ABOVE_GROUND_HIGH_PRECISION_cm:
00709       lv1 = (float) lev;
00710       break;
00711     case GRIB_LEVEL_ISOTHERMAL_K:
00712       lv1 = (float) (lev/100.0);
00713       break;
00714     case GRIB_LEVEL_SIGMA:
00715     case GRIB_LEVEL_ETA:
00716       lv1 = (float) (lev/10000.0);
00717       break;
00718     case GRIB_LEVEL_LAYER_HYBRID:
00719     case GRIB_LEVEL_LAYER_DEPTH_BELOW_SURFACE_cm:
00720     case GRIB_LEVEL_LAYER_PRESSURE_DIFFERENCE_FROM_GROUND_mb:
00721       lv1 = (float) o11;
00722       lv2 = (float) o12;
00723       break;
00724     case GRIB_LEVEL_LAYER_ISOBARIC_mb:
00725       lv1 = (float) o11*10.0;
00726       lv2 = (float) o12*10.0;
00727       break;
00728     case GRIB_LEVEL_LAYER_ALTITUDE_ABOVE_MSL_m:
00729     case GRIB_LEVEL_LAYER_HEIGHT_ABOVE_GROUND_m:
00730       lv1 = (float) o11*100.0;
00731       lv2 = (float) o12*100.0;
00732       break;
00733     case GRIB_LEVEL_LAYER_SIGMA:
00734     case GRIB_LEVEL_LAYER_ETA:
00735       lv1 = (float) o11/100.0;
00736       lv2 = (float) o12/100.0;
00737       break;
00738     case GRIB_LEVEL_LAYER_ISENTROPIC_K:
00739       lv1 = (float) (475-o11);
00740       lv2 = (float) (475-o12);
00741       break;
00742     case GRIB_LEVEL_LAYER_ISOBARIC_HIGH_PRECISION_mb:
00743       lv1 = (float) (1100-o11);
00744       lv2 = (float) (1100-o12);
00745       break;
00746     case GRIB_LEVEL_LAYER_SIGMA_HIGH_PRECISION:
00747       lv1 = (float) o11/1000.0;
00748       lv2 = (float) o12/1000.0;
00749       break;
00750     case GRIB_LEVEL_LAYER_ISOBARIC_MIXED_PRECISION_mb:
00751       lv1 = (float) o11;
00752       lv2 = (float) (1100-o12);
00753       break;
00754     default:
00755       std::cerr << "Unknown Level is used !!!!" << std::endl;
00756   }
00757   return;
00758 }
00759 
00760 void GRIB_LEVEL::set_pressure(float plev)
00761 {
00762   type = GRIB_LEVEL_ISOBARIC_mb;
00763   lv1 = plev;
00764   lv2 = 0.0;
00765   return;
00766 }
00767 
00768 void GRIB_LEVEL::set_height(float hgt)
00769 {
00770   type = GRIB_LEVEL_HEIGHT_ABOVE_GROUND_m;
00771   lv1 = hgt;
00772   lv2 = 0.0;
00773   return;
00774 }
00775 
00776 void GRIB_LEVEL::set_seadepth(float dpt)
00777 {
00778   type = GRIB_LEVEL_DEPTH_BELOW_SEA_m;
00779   lv1 = dpt;
00780   lv2 = 0.0;
00781   return;
00782 }
00783 
00784 void GRIB_LEVEL::set_isentropic(float temp)
00785 {
00786   type = GRIB_LEVEL_ISENTROPIC_K;
00787   lv1 = temp;
00788   lv2 = 0.0;
00789   return;
00790 }
00791 
00792 void GRIB_LEVEL::set_sigma(float sigma)
00793 {
00794   type = GRIB_LEVEL_SIGMA;
00795   lv1 = sigma;
00796   lv2 = 0.0;
00797   return;
00798 }
00799 
00800 void GRIB_LEVEL::set_surface( )
00801 {
00802   type = GRIB_LEVEL_SURFACE;
00803   lv1 = 0.0;
00804   lv2 = 0.0;
00805   return;
00806 }
00807 
00808 std::ostream& operator<< ( std::ostream& os, GRIB_LEVEL &l )
00809 {
00810   os << l.leveldesc( );
00811   return os;
00812 }
00813 
00814 std::string GRIB_LEVEL::leveldesc( )
00815 {
00816   std::stringstream s;
00817   switch (type)
00818   {
00819     case GRIB_LEVEL_SURFACE:
00820       s << "Ground or water surface";
00821       break;
00822     case GRIB_LEVEL_CLOUD_BASE:
00823       s << "Cloud base";
00824       break;
00825     case GRIB_LEVEL_CLOUD_TOP:
00826       s << "Cloud top";
00827       break;
00828     case GRIB_LEVEL_ISOTHERM_0_DEG:
00829       s << "Isotherm level at 0 Celsius";
00830       break;
00831     case GRIB_LEVEL_ADIABATIC_CONDENSATION_LIFTED_FROM_SURFACE:
00832       s << "Level of adiabatic condensation lifted from surface";
00833       break;
00834     case GRIB_LEVEL_MAXIMUM_WIND:
00835       s << "Level of maximum wind";
00836       break;
00837     case GRIB_LEVEL_TROPOPAUSE:
00838       s << "Tropopause level";
00839       break;
00840     case GRIB_LEVEL_NOMINAL_ATMOSPHERE_TOP:
00841       s << "Nominal atmosphere top";
00842       break;
00843     case GRIB_LEVEL_MEAN_SEA_LEVEL:
00844       s << "Mean Sea Level";
00845       break;
00846     case GRIB_LEVEL_ENTIRE_ATMOSPHERE:
00847       s << "Entire atmosphere as single layer";
00848       break;
00849     case GRIB_LEVEL_ENTIRE_OCEAN:
00850       s << "Entire ocean as single layer";
00851       break;
00852     case GRIB_LEVEL_ISOBARIC_mb:
00853       s << lv1 << " mb";
00854       break;
00855     case GRIB_LEVEL_ALTITUDE_ABOVE_MSL_m:
00856       s << lv1 << " m above MSL";
00857       break;
00858     case GRIB_LEVEL_HEIGHT_ABOVE_GROUND_m:
00859       s << lv1 << " m above ground";
00860       break;
00861     case GRIB_LEVEL_HYBRID:
00862       s << lv1 << " hybrid level";
00863       break;
00864     case GRIB_LEVEL_DEPTH_BELOW_SURFACE_cm:
00865       s << lv1 << " cm below surface";
00866       break;
00867     case GRIB_LEVEL_ISENTROPIC_K:
00868       s << lv1 << " K isentropic";
00869       break;
00870     case GRIB_LEVEL_PRESSURE_DIFFERENCE_FROM_GROUND_mb:
00871       s << lv1 << " mb difference from ground";
00872       break;
00873     case GRIB_LEVEL_POTENTIAL_VORTICITY_SURFACE_PV_UNITS:
00874       s << lv1 << " PV units";
00875       break;
00876     case GRIB_LEVEL_ISOBARIC_Pa:
00877       s << lv1 << " Pa";
00878       break;
00879     case GRIB_LEVEL_DEPTH_BELOW_SEA_m:
00880       s << lv1 << " m below sea";
00881       break;
00882     case GRIB_LEVEL_HEIGHT_ABOVE_GROUND_HIGH_PRECISION_cm:
00883       s << lv1 << " cm above ground (high precision)";
00884       break;
00885     case GRIB_LEVEL_ISOTHERMAL_K:
00886       s << lv1 << " K isotherm";
00887       break;
00888     case GRIB_LEVEL_SIGMA:
00889       s << lv1 << " sigma";
00890       break;
00891     case GRIB_LEVEL_ETA:
00892       s << lv1 << " eta";
00893       break;
00894     case GRIB_LEVEL_LAYER_ISOBARIC_mb:
00895       s << lv1 << "-" << lv2 << " mb layer";
00896       break;
00897     case GRIB_LEVEL_LAYER_ALTITUDE_ABOVE_MSL_m:
00898       s << lv1 << "-" << lv2 << " m above sea level layer";
00899       break;
00900     case GRIB_LEVEL_LAYER_HEIGHT_ABOVE_GROUND_m:
00901       s << lv1 << "-" << lv2 << " m height above ground layer";
00902       break;
00903     case GRIB_LEVEL_LAYER_SIGMA:
00904       s << lv1 << "-" << lv2 << " sigma layer";
00905       break;
00906     case GRIB_LEVEL_LAYER_ETA:
00907       s << lv1 << "-" << lv2 << " eta layer";
00908       break;
00909     case GRIB_LEVEL_LAYER_ISENTROPIC_K:
00910       s << lv1 << "-" << lv2 << " K isentropic layer";
00911       break;
00912     case GRIB_LEVEL_LAYER_HYBRID:
00913       s << lv1 << "-" << lv2 << " hybrid layer";
00914       break;
00915     case GRIB_LEVEL_LAYER_DEPTH_BELOW_SURFACE_cm:
00916       s << lv1 << "-" << lv2 << " cm below suface layer";
00917       break;
00918     case GRIB_LEVEL_LAYER_PRESSURE_DIFFERENCE_FROM_GROUND_mb:
00919       s << lv1 << "-" << lv2 << " mb difference from ground layer";
00920       break;
00921     case GRIB_LEVEL_LAYER_ISOBARIC_HIGH_PRECISION_mb:
00922       s << lv1 << "-" << lv2 << " mb high precision layer";
00923       break;
00924     case GRIB_LEVEL_LAYER_SIGMA_HIGH_PRECISION:
00925       s << lv1 << "-" << lv2 << " sigma high precision layer";
00926       break;
00927     case GRIB_LEVEL_LAYER_ISOBARIC_MIXED_PRECISION_mb:
00928       s << lv1 << "-" << lv2 << " mb mixed precision layer";
00929       break;
00930     default:
00931       throw;
00932   }
00933   return s.str( );
00934 }
00935 
00936 bool GRIB_LEVEL::is_LevelPressure( )
00937 {
00938   return (type == GRIB_LEVEL_ISOBARIC_mb);
00939 }
00940 
00941 bool GRIB_LEVEL::is_LevelHeight( )
00942 {
00943   return (type == GRIB_LEVEL_HEIGHT_ABOVE_GROUND_m);
00944 }
00945 
00946 bool GRIB_LEVEL::is_Surface( )
00947 {
00948   return (type == GRIB_LEVEL_SURFACE);
00949 }
00950 
00951 bool GRIB_LEVEL::is_MeanSeaLevel( )
00952 {
00953   return (type == GRIB_LEVEL_MEAN_SEA_LEVEL);
00954 }
00955 
00956 // ############################################################################
00957 // GRIB Grid implementation
00958 // ############################################################################
00959 
00960 void GRIB_GRID_regular_latlon::set(float lat1, float lat2,
00961                                    float lon1, float lon2,
00962                                    float dlat, float dlon)
00963 {
00964   this->lat1 = lat1;
00965   this->lon1 = lon1;
00966   this->lat2 = lat2;
00967   this->lon2 = lon2;
00968   this->dlat = dlat;
00969   this->dlon = dlon;
00970   return;
00971 }
00972 
00973 std::ostream& operator<< ( std::ostream& os, GRIB_GRID_regular_latlon &g )
00974 {
00975   os << "               Regular latitude/longitude projection" << std::endl
00976      << "               "
00977      << "Latitude  " << g.lat1 << " to " << g.lat2
00978      << " by " << g.dlat << std::endl
00979      << "               "
00980      << "Longitude " << g.lon1 << " to " << g.lon2
00981      << " by " << g.dlon;
00982   return os;
00983 }
00984 
00985 void GRIB_GRID_gaussian_latlon::set(float lat1, float lat2,
00986                                     float lon1, float lon2,
00987                                     float dlon, float N)
00988 {
00989   this->lat1 = lat1;
00990   this->lon1 = lon1;
00991   this->lat2 = lat2;
00992   this->lon2 = lon2;
00993   this->dlon = dlon;
00994   this->N    = N;
00995   return;
00996 }
00997 
00998 std::ostream& operator<< ( std::ostream& os, GRIB_GRID_gaussian_latlon &g )
00999 {
01000   os << "               Gaussian latitude/longitude projection" << std::endl
01001      << "               Latitude  " << g.lat1 << " to " << g.lat2
01002      << " " << g.N << " latitude circles" << std::endl
01003      << "               Longitude " << g.lon1 << " to " << g.lon2
01004      << " by " << g.dlon;
01005   return os;
01006 }
01007 
01008 void GRIB_GRID_polar_stereographic::set(float lat1, float lon1, float lov,
01009                                         float dx, float dy, bool pole)
01010 {
01011   this->lat1 = lat1;
01012   this->lon1 = lon1;
01013   this->lov  = lov;
01014   this->dx   = dx;
01015   this->dy   = dy;
01016   this->pole = pole;
01017   return;
01018 }
01019 
01020 std::ostream& operator<< ( std::ostream& os, GRIB_GRID_polar_stereographic &g )
01021 {
01022   os << "               Polar stereographic projection" << std::endl
01023      << "               "
01024      << "First point Latitude " << g.lat1 << ", Longitude " << g.lon1
01025      << std::endl << "Orientation longitude " << g.lov << std::endl
01026      << "               "
01027      << "Dx " << g.dx << " Km, Dy " << g.dy << "Km, "
01028      << (g.pole ? "North Polar": "South Polar") << std::endl;
01029   return os;
01030 }
01031 
01032 void GRIB_GRID_lambert_conformal::set(float lat1, float lon1, float lov,
01033                                       float latin1, float latin2,
01034                                       float latsp, float lonsp,
01035                                       float dx, float dy,
01036                                       bool pole, bool bipolar)
01037 {
01038   this->lat1    = lat1;
01039   this->lon1    = lon1;
01040   this->lov     = lov;
01041   this->latin1  = latin1;
01042   this->latin2  = latin2;
01043   this->latsp   = latsp;
01044   this->lonsp   = lonsp;
01045   this->dx      = dx;
01046   this->dy      = dy;
01047   this->pole    = pole;
01048   this->bipolar = bipolar;
01049   return;
01050 }
01051 
01052 std::ostream& operator<< ( std::ostream& os, GRIB_GRID_lambert_conformal &g )
01053 {
01054   os << "               Lambert conformal projection" << std::endl
01055      << "               "
01056      << "First point Latitude " << g.lat1 << ", Longitude " << g.lon1
01057      << std::endl << "Orientation longitude " << g.lov << std::endl
01058      << "               "
01059      << "Secant latitude1 " << g.latin1 << ", latitude2 " << g.latin2
01060      << std::endl << "South Pole Latitude " << g.latsp
01061      << ", Longitude " << g.lonsp << std::endl
01062      << "               "
01063      << "Dx " << g.dx << " Km, Dy " << g.dy << "Km, "
01064      << (g.pole ? "North Polar": "South Polar") << ", "
01065      << (g.bipolar ? " bipolar symmetric" : "one center") << std::endl;
01066   return os;
01067 }
01068 
01069 void GRIB_GRID_mercator::set(float lat1, float lon1,
01070                              float lat2, float lon2,
01071                              float dx, float dy, float latin)
01072 {
01073   this->lat1  = lat1;
01074   this->lon1  = lon1;
01075   this->lat2  = lat2;
01076   this->lon2  = lon2;
01077   this->dx    = dx;
01078   this->dy    = dy;
01079   this->latin = latin;
01080   return;
01081 }
01082 
01083 std::ostream& operator<< ( std::ostream& os, GRIB_GRID_mercator &g )
01084 {
01085   os << "               Mercator projection" << std::endl
01086      << "               "
01087      << "Latitude " << g.lat1 << " to " << g.lat2
01088      << " by " << g.dy << " Km " << std::endl
01089      << "Longitude " << g.lon1 << " to " << g.lon2
01090      << "               "
01091      << " by " << g.dx << " Km " << std::endl
01092      << "               "
01093      << "Latin " << g.latin << std::endl;
01094   return os;
01095 }
01096 
01097 void GRIB_GRID_spaceview::set(float lap, float lop, float dx, float dy,
01098                               float Xp, float Yp, float orient, float Nr)
01099 {
01100   this->lap    = lap;
01101   this->lop    = lop;
01102   this->dx     = dx;
01103   this->dy     = dy;
01104   this->Xp     = Xp;
01105   this->Yp     = Yp;
01106   this->orient = orient;
01107   this->Nr     = Nr;
01108   return;
01109 }
01110 
01111 std::ostream& operator<< ( std::ostream& os, GRIB_GRID_spaceview &g )
01112 {
01113   os << "               Space view projection" << std::endl
01114      << "               Sub satellite point lat/lon: "
01115      << g.lap << ", " << g.lop << std::endl
01116      << "               Apparent diameter of earth X,Y: "
01117      << g.dx << ", " << g.dy << std::endl
01118      << "               Sub satellite point X,Y: "
01119      << g.Xp << ", " << g.Yp << std::endl
01120      << "               Orient " << g.orient << ", Camera H " << g.Nr
01121      << std::endl;
01122   return os;
01123 }
01124 
01125 void GRIB_GRID_spherical_harmonic::set(int J, int K, int M, int rt, int csm)
01126 {
01127   this->J = J;
01128   this->K = K;
01129   this->M = M;
01130   representation = (GRIB_GRID_SPECTRAL_REPRESENTATION) rt;
01131   storage_method = (GRIB_GRID_COEFFICIENT_STORAGE_METHOD) csm;
01132   return;
01133 }
01134 
01135 std::ostream& operator<< ( std::ostream& os, GRIB_GRID_spherical_harmonic &g )
01136 {
01137   os << "               Spherical harmonic coefficients" << std::endl
01138      << "               J, K, M : "
01139      << g.J << ", " << g.K << ", " << g.M << std::endl
01140      << "               Spectral representation: "
01141      << ((g.representation == g.SR_associated_legendre_polynomials_first_kind) ?
01142         "Associated Legendre polynomials of first kind" :
01143         "Sperical armonics - complex packing")
01144      << "               Storage Method : "
01145      << ((g.storage_method == g.CSM_normal) ?  "Normal" : "Complex packing")
01146      << std::endl;
01147   return os;
01148 }
01149 
01150 GRIB_GRID::GRIB_GRID( )
01151 {
01152   grid_code = 0;
01153   type = GRIB_GRID_UNKNOWN;
01154   is_dirincgiven = true;
01155   is_earth_spheroid = false;
01156   is_uv_grid = false;
01157   is_x_negative = false;
01158   is_y_negative = false;
01159   is_fortran = false;
01160   nxny = nx = ny = 0;
01161 }
01162 
01163 void GRIB_GRID::set_size(int nx, int ny)
01164 {
01165   this->nx = nx;
01166   this->ny = ny;
01167   nxny = nx*ny;
01168   return;
01169 }
01170 
01171 void GRIB_GRID::set_number(int code)
01172 {
01173   grid_code = code;
01174   return;
01175 }
01176 
01177 void GRIB_GRID::set_regular_latlon(float lat1, float lat2,
01178                                    float lon1, float lon2,
01179                                    float dlat, float dlon)
01180 {
01181   grid_code = 255;
01182   type = GRIB_GRID_REGULAR_LATLON;
01183   ll.set(lat1, lat2, lon1, lon2, dlat, dlon);
01184   return;
01185 }
01186 
01187 void GRIB_GRID::set_gaussian_latlon(float lat1, float lat2,
01188                                     float lon1, float lon2,
01189                                     float dlon, float N)
01190 {
01191   grid_code = 255;
01192   type = GRIB_GRID_GAUSSIAN;
01193   gl.set(lat1, lat2, lon1, lon2, dlon, N);
01194   return;
01195 }
01196 
01197 void GRIB_GRID::set_polar_stereo(float lat1, float lon1, float lov,
01198                                  float dx, float dy, bool pole)
01199 {
01200   grid_code = 255;
01201   type = GRIB_GRID_POLAR_STEREOGRAPHIC;
01202   ps.set(lat1, lon1, lov, dx, dy, pole);
01203   return;
01204 }
01205 
01206 void GRIB_GRID::set_lambert_conformal(float lat1, float lon1, float lov,
01207                                       float latin1, float latin2,
01208                                       float latsp, float lonsp,
01209                                       float dx, float dy,
01210                                       bool pole, bool bipolar)
01211 {
01212   grid_code = 255;
01213   type = GRIB_GRID_LAMBERT_CONFORMAL;
01214   lc.set(lat1, lon1, lov, latin1, latin2, latsp, lonsp, dx, dy, pole, bipolar);
01215   return;
01216 }
01217 
01218 void GRIB_GRID::set_mercator(float lat1, float lon1, float lat2, float lon2,
01219                              float dx, float dy, float latin)
01220 {
01221   grid_code = 255;
01222   type = GRIB_GRID_MERCATOR;
01223   mc.set(lat1, lon1, lat2, lon2, dx, dy, latin);
01224   return;
01225 }
01226 
01227 void GRIB_GRID::set_spaceview(float lap, float lop, float dx, float dy,
01228                               float Xp, float Yp, float orient, float Nr)
01229 {
01230   grid_code = 255;
01231   type = GRIB_GRID_SPACEVIEW;
01232   sp.set(lap, lop, dx, dy, Xp, Yp, orient, Nr);
01233   return;
01234 }
01235 
01236 void GRIB_GRID::set_spherical_harmonic(int J, int K, int M, int rt, int csm)
01237 {
01238   grid_code = 255;
01239   type = GRIB_GRID_SPHERICAL_HARMONIC_COE;
01240   sa.set(J, K, M, rt, csm);
01241   return;
01242 }
01243 
01244 void GRIB_GRID::set_earth_spheroid( ) { is_earth_spheroid = true; }
01245 void GRIB_GRID::set_uv_grid( ) { is_uv_grid = true; }
01246 void GRIB_GRID::set_x_negative( ) { is_x_negative = true; }
01247 void GRIB_GRID::set_y_negative( ) { is_y_negative = true; }
01248 void GRIB_GRID::set_fortran_indexing( ) { is_fortran = true; }
01249 
01250 std::ostream& operator<< ( std::ostream& os, GRIB_GRID &g )
01251 {
01252   os << "Size: " << g.nx << " x " << g.ny << " ("
01253      << g.nxny << ")" << std::endl;
01254   if (g.grid_code != 0 && g.grid_code != 255)
01255   {
01256     os << "          GRID IDENTIFICATION NUMBER " << g.grid_code;
01257     return os;
01258   }
01259   if (! g.is_dirincgiven)
01260     os << "Direction increment are NOT given!" << std::endl;
01261   if (g.is_earth_spheroid)
01262     os << "Earth is spheroid!" << std::endl;
01263   if (g.is_uv_grid)
01264     os << "U-V vector components are GRID relative!" << std::endl;
01265   if (g.is_x_negative)
01266     os << "X scan mode is reversed (EW)!" << std::endl;
01267   if (g.is_y_negative)
01268     os << "Y scan mode is reversed (NS)!" << std::endl;
01269   if (g.is_fortran)
01270     os << "Fortran indexing (columnar)!" << std::endl;
01271   switch (g.type)
01272   {
01273     case GRIB_GRID_REGULAR_LATLON:
01274       os << g.ll;
01275       break;
01276     case GRIB_GRID_GAUSSIAN:
01277       os << g.gl;
01278       break;
01279     case GRIB_GRID_POLAR_STEREOGRAPHIC:
01280       os << g.ps;
01281       break;
01282     case GRIB_GRID_LAMBERT_CONFORMAL:
01283       os << g.lc;
01284       break;
01285     case GRIB_GRID_MERCATOR:
01286       os << g.mc;
01287       break;
01288     case GRIB_GRID_SPACEVIEW:
01289       os << g.sp;
01290       break;
01291     case GRIB_GRID_SPHERICAL_HARMONIC_COE:
01292       os << g.sa;
01293       break;
01294     default:
01295       os << "Unsupported Grid is being used." << std::endl
01296          << "Code is: " << g.type << std::endl
01297          << "Grid Descripion is: " << std::endl
01298          << std::setw(3) << std::setfill('0')
01299          << (int) g.gds[6] << " "  << (int) g.gds[7] << " "
01300          << (int) g.gds[8] << " "  << (int) g.gds[9] << " "
01301          << (int) g.gds[10] << " " << (int) g.gds[11] << " "
01302          << (int) g.gds[12] << " " << (int) g.gds[13] << " "
01303          << (int) g.gds[14] << " " << (int) g.gds[15] << " "
01304          << (int) g.gds[16] << " " << (int) g.gds[17] << " "
01305          << (int) g.gds[18] << " " << (int) g.gds[19] << " "
01306          << (int) g.gds[20] << std::endl
01307          << (int) g.gds[21] << " " << (int) g.gds[22] << " "
01308          << (int) g.gds[23] << " " << (int) g.gds[24] << " "
01309          << (int) g.gds[25] << " " << (int) g.gds[26] << " "
01310          << (int) g.gds[27] << " " << (int) g.gds[28] << " "
01311          << (int) g.gds[29] << " " << (int) g.gds[30] << " "
01312          << (int) g.gds[31] << " " << (int) g.gds[32] << " "
01313          << (int) g.gds[33] << " " << (int) g.gds[34] << " "
01314          << (int) g.gds[35] << std::endl
01315          << (int) g.gds[36] << " " << (int) g.gds[37] << " "
01316          << (int) g.gds[38] << " " << (int) g.gds[39] << " "
01317          << (int) g.gds[40] << " " << (int) g.gds[41] << " "
01318          << (int) g.gds[42] << " " << (int) g.gds[43] << std::endl;
01319   }
01320   return os;
01321 }
01322 
01323 unsigned char *GRIB_GRID::Encode( )
01324 {
01325   unsigned char *xgds = 0;
01326 
01327   if (grid_code != 255) return 0;
01328 
01329   int mode = 0, scan = 0, pole = 0;
01330   if (is_dirincgiven)    mode += 128; // bit 1
01331   if (is_earth_spheroid) mode += 64;  // bit 2
01332   if (is_uv_grid)        mode += 8;   // bit 5
01333   if (is_x_negative)     scan += 128; // bit 1
01334   if (is_y_negative)     scan += 64;  // bit 2
01335   if (is_fortran)        scan += 32;  // bit 3
01336 
01337   switch (type)
01338   {
01339     case GRIB_GRID_REGULAR_LATLON:
01340       xgds = mk_GDS(NULL, WGRIB_ENCODE_INIT, 32, 0,
01341                    WGRIB_ENCODE_BYTE,    4,  255,
01342                    WGRIB_ENCODE_BYTE,    5,  GRIB_GRID_REGULAR_LATLON,
01343                    WGRIB_ENCODE_2BYTES,  6,  nx,
01344                    WGRIB_ENCODE_2BYTES,  8,  ny,
01345                    WGRIB_ENCODE_S3BYTES, 10, (int) (1000.0*(ll.lat1)),
01346                    WGRIB_ENCODE_S3BYTES, 13, (int) (1000.0*(ll.lon1)),
01347                    WGRIB_ENCODE_BYTE,    16, mode,
01348                    WGRIB_ENCODE_S3BYTES, 17, (int) (1000.0*(ll.lat2)),
01349                    WGRIB_ENCODE_S3BYTES, 20, (int) (1000.0*(ll.lon2)),
01350                    WGRIB_ENCODE_S2BYTES, 23, (int) (1000.0*(ll.dlon)),
01351                    WGRIB_ENCODE_S2BYTES, 25, (int) (1000.0*(ll.dlat)),
01352                    WGRIB_ENCODE_BYTE,    27, scan,   WGRIB_ENCODE_END);
01353       break;
01354     case GRIB_GRID_POLAR_STEREOGRAPHIC:
01355       pole = ps.pole ? 0 : 128;
01356       xgds = mk_GDS(NULL, WGRIB_ENCODE_INIT, 32, 0,
01357                    WGRIB_ENCODE_BYTE,    4,  255,
01358                    WGRIB_ENCODE_BYTE,    5,  GRIB_GRID_POLAR_STEREOGRAPHIC,
01359                    WGRIB_ENCODE_2BYTES,  6,  nx,
01360                    WGRIB_ENCODE_2BYTES,  8,  ny,
01361                    WGRIB_ENCODE_S3BYTES, 10, (int) (1000.0*(ps.lat1)),
01362                    WGRIB_ENCODE_S3BYTES, 13, (int) (1000.0*(ps.lon1)),
01363                    WGRIB_ENCODE_BYTE,    16, mode,
01364                    WGRIB_ENCODE_S3BYTES, 17, (int) (1000.0*(ps.lov)),
01365                    WGRIB_ENCODE_S3BYTES, 20, (int) (1000.0*(ps.dx)),
01366                    WGRIB_ENCODE_S3BYTES, 23, (int) (1000.0*(ps.dy)),
01367                    WGRIB_ENCODE_BYTE,    26, pole,
01368                    WGRIB_ENCODE_BYTE,    27, scan,   WGRIB_ENCODE_END);
01369       break;
01370     case GRIB_GRID_LAMBERT_CONFORMAL:
01371       pole = 0;
01372       if      (  lc.pole &&   lc.bipolar) pole = 64;
01373       else if (! lc.pole && ! lc.bipolar) pole = 128;
01374       else if (! lc.pole &&   lc.bipolar) pole = 192;
01375       xgds = mk_GDS(NULL, WGRIB_ENCODE_INIT, 42, 0,
01376                    WGRIB_ENCODE_BYTE,    4,  255,
01377                    WGRIB_ENCODE_BYTE,    5,  GRIB_GRID_LAMBERT_CONFORMAL,
01378                    WGRIB_ENCODE_2BYTES,  6,  nx,
01379                    WGRIB_ENCODE_2BYTES,  8,  ny,
01380                    WGRIB_ENCODE_S3BYTES, 10, (int) (1000.0*(lc.lat1)),
01381                    WGRIB_ENCODE_S3BYTES, 13, (int) (1000.0*(lc.lon1)),
01382                    WGRIB_ENCODE_BYTE,    16, mode,
01383                    WGRIB_ENCODE_S3BYTES, 17, (int) (1000.0*(lc.lov)),
01384                    WGRIB_ENCODE_S3BYTES, 20, (int) (1000.0*(lc.dx)),
01385                    WGRIB_ENCODE_S3BYTES, 23, (int) (1000.0*(lc.dy)),
01386                    WGRIB_ENCODE_BYTE,    26, pole,
01387                    WGRIB_ENCODE_BYTE,    27, scan,
01388                    WGRIB_ENCODE_S3BYTES, 28, (int) (1000.0*(lc.latin1)),
01389                    WGRIB_ENCODE_S3BYTES, 31, (int) (1000.0*(lc.latin2)),
01390                    WGRIB_ENCODE_S3BYTES, 34, (int) (1000.0*(lc.latsp)),
01391                    WGRIB_ENCODE_S3BYTES, 37, (int) (1000.0*(lc.lonsp)),
01392                    WGRIB_ENCODE_END);
01393       break;
01394     case GRIB_GRID_MERCATOR:
01395       xgds = mk_GDS(NULL, WGRIB_ENCODE_INIT, 42, 0,
01396                    WGRIB_ENCODE_BYTE,    4,  255,
01397                    WGRIB_ENCODE_BYTE,    5,  GRIB_GRID_MERCATOR,
01398                    WGRIB_ENCODE_2BYTES,  6,  nx,
01399                    WGRIB_ENCODE_2BYTES,  8,  ny,
01400                    WGRIB_ENCODE_S3BYTES, 10, (int) (1000.0*(mc.lat1)),
01401                    WGRIB_ENCODE_S3BYTES, 13, (int) (1000.0*(mc.lon1)),
01402                    WGRIB_ENCODE_BYTE,    16, mode,
01403                    WGRIB_ENCODE_S3BYTES, 17, (int) (1000.0*(mc.lat2)),
01404                    WGRIB_ENCODE_S3BYTES, 20, (int) (1000.0*(mc.lon2)),
01405                    WGRIB_ENCODE_S3BYTES, 23, (int) (1000.0*(mc.latin)),
01406                    WGRIB_ENCODE_BYTE,    27, scan,
01407                    WGRIB_ENCODE_S3BYTES, 28, (int) (1000.0*(mc.dx)),
01408                    WGRIB_ENCODE_S3BYTES, 31, (int) (1000.0*(mc.dy)),
01409                    WGRIB_ENCODE_END);
01410       break;
01411     case GRIB_GRID_SPACEVIEW:
01412       xgds = mk_GDS(NULL, WGRIB_ENCODE_INIT, 44, 0,
01413                    WGRIB_ENCODE_BYTE,    4,  255,
01414                    WGRIB_ENCODE_BYTE,    5,  GRIB_GRID_SPACEVIEW,
01415                    WGRIB_ENCODE_2BYTES,  6,  nx,
01416                    WGRIB_ENCODE_2BYTES,  8,  ny,
01417                    WGRIB_ENCODE_S3BYTES, 10, (int) (1000.0*(sp.lap)),
01418                    WGRIB_ENCODE_S3BYTES, 13, (int) (1000.0*(sp.lop)),
01419                    WGRIB_ENCODE_BYTE,    16, mode,
01420                    WGRIB_ENCODE_S3BYTES, 17, (int) (1000.0*(sp.dx)),
01421                    WGRIB_ENCODE_S3BYTES, 20, (int) (1000.0*(sp.dy)),
01422                    WGRIB_ENCODE_S2BYTES, 23, (int) sp.Xp,
01423                    WGRIB_ENCODE_S2BYTES, 25, (int) sp.Yp,
01424                    WGRIB_ENCODE_BYTE,    27, scan,
01425                    WGRIB_ENCODE_S3BYTES, 28, (int) (1000.0*(sp.orient)),
01426                    WGRIB_ENCODE_S3BYTES, 31, (int) (1000.0*(sp.Nr)),
01427                    WGRIB_ENCODE_END);
01428       break;
01429     case GRIB_GRID_SPHERICAL_HARMONIC_COE:
01430       xgds = mk_GDS(NULL, WGRIB_ENCODE_INIT, 32, 0,
01431                    WGRIB_ENCODE_BYTE,    4,  255,
01432                    WGRIB_ENCODE_BYTE,    5,  GRIB_GRID_SPHERICAL_HARMONIC_COE,
01433                    WGRIB_ENCODE_2BYTES,  6,  sa.J,
01434                    WGRIB_ENCODE_2BYTES,  8,  sa.K,
01435                    WGRIB_ENCODE_2BYTES, 10,  sa.M,
01436                    WGRIB_ENCODE_BYTE,   12,  sa.representation,
01437                    WGRIB_ENCODE_BYTE,   13,  sa.storage_method,
01438                    WGRIB_ENCODE_END);
01439       break;
01440     default:
01441       xgds = mk_GDS(NULL, WGRIB_ENCODE_INIT, 32, 0,
01442                     WGRIB_ENCODE_BYTE,    4,  255,
01443                     WGRIB_ENCODE_END);
01444       memcpy(xgds+4, gds+4, 28);
01445       break;
01446   }
01447   return xgds;
01448 }
01449 
01450 void GRIB_GRID::Decode(unsigned char *pds,
01451                        unsigned char *xgds,
01452                        unsigned char *bms,
01453                        unsigned char *bds)
01454 {
01455   // Get grid dimension
01456   ny = 1;
01457 
01458   if (xgds != NULL)
01459   {
01460     if (GDS_LEN(xgds) > 44)
01461     {
01462       std::cerr << "Sorry, thinned grids NOT supported." << std::endl;
01463       throw;
01464     }
01465 
01466     memcpy(gds, xgds, GDS_LEN(xgds));
01467 
01468     GDS_grid(gds, bds, &nx, &ny, &nxny);
01469     type = (t_enum_GRIB_GRIDS) GDS_DataType(gds);
01470     switch (type)
01471     {
01472       case GRIB_GRID_REGULAR_LATLON:
01473         ll.set(0.001*GDS_LatLon_La1(gds), 0.001*GDS_LatLon_La2(gds),
01474                0.001*GDS_LatLon_Lo1(gds), 0.001*GDS_LatLon_Lo2(gds),
01475                0.001*GDS_LatLon_dy(gds),  0.001*GDS_LatLon_dx(gds));
01476         break;
01477       case GRIB_GRID_GAUSSIAN:
01478         gl.set(0.001*GDS_LatLon_La1(gds), 0.001*GDS_LatLon_La2(gds),
01479                0.001*GDS_LatLon_Lo1(gds), 0.001*GDS_LatLon_Lo2(gds),
01480                0.001*GDS_LatLon_dx(gds),  0.001*GDS_Gaussian_nlat(gds));
01481         break;
01482       case GRIB_GRID_POLAR_STEREOGRAPHIC:
01483         ps.set(0.001*GDS_Polar_La1(gds), 0.001*GDS_Polar_Lo1(gds),
01484                0.001*GDS_Polar_Lov(gds),
01485                0.001*GDS_Polar_Dx(gds), 0.001*GDS_Polar_Dy(gds),
01486                (GDS_Polar_pole(gds) ? true : false));
01487         break;
01488       case GRIB_GRID_LAMBERT_CONFORMAL:
01489         lc.set(0.001*GDS_Lambert_La1(gds), 0.001*GDS_Lambert_Lo1(gds),
01490                0.001*GDS_Lambert_Lov(gds), 0.001*GDS_Lambert_Latin1(gds),
01491                0.001*GDS_Lambert_Latin2(gds), 0.001*GDS_Lambert_LatSP(gds),
01492                0.001*GDS_Lambert_LonSP(gds), 0.001*GDS_Lambert_dx(gds),
01493                0.001*GDS_Lambert_dy(gds), (GDS_Lambert_NP(gds) ? true : false),
01494                (((gds[26] & 64) == 0) ? true : false));
01495         break;
01496       case GRIB_GRID_MERCATOR:
01497         mc.set(0.001*GDS_Merc_La1(gds), 0.001*GDS_Merc_Lo1(gds),
01498                0.001*GDS_Merc_La2(gds), 0.001*GDS_Merc_Lo2(gds),
01499                0.001*GDS_Merc_dx(gds), 0.001*GDS_Merc_dy(gds),
01500                0.001*GDS_Merc_Latin(gds));
01501         break;
01502       case GRIB_GRID_SPHERICAL_HARMONIC_COE:
01503         sa.set(GDS_Harmonic_nj(gds), GDS_Harmonic_nk(gds),
01504                GDS_Harmonic_nm(gds), GDS_Harmonic_type(gds),
01505                GDS_Harmonic_mode(gds));
01506         break;
01507       case GRIB_GRID_SPACEVIEW:
01508         sp.set(0.001*GDS_Spaceview_lap(gds), 0.001*GDS_Spaceview_lop(gds),
01509                0.001*GDS_Spaceview_dx(gds), 0.001*GDS_Spaceview_dy(gds),
01510                GDS_Spaceview_Xp(gds), GDS_Spaceview_Yp(gds),
01511                0.001*GDS_Spaceview_or(gds), 0.001*GDS_Spaceview_nr(gds));
01512         break;
01513       default:
01514         break;
01515     }
01516 
01517     is_dirincgiven = (gds[16] & 128);
01518     is_earth_spheroid = (gds[16] & 64);
01519     is_uv_grid = (gds[16] & 8);
01520     is_x_negative = (gds[27] & 128);
01521     is_y_negative = (gds[27] & 64);
01522     is_fortran = (gds[27] & 32);
01523   }
01524   else if (bms != NULL)
01525     nxny = nx = ((bms[4]<<8) + bms[5]);
01526   else
01527   {
01528     if (BDS_NumBits(bds) == 0)
01529       nxny = nx = 1;
01530     else
01531       nxny = nx = BDS_NValues(bds);
01532   }
01533 
01534   grid_code = PDS_Grid(pds);
01535 
01536   return;
01537 }
01538 
01539 // ############################################################################
01540 // GRIB Field implementation
01541 // ############################################################################
01542 
01543 GRIB_FIELD::GRIB_FIELD( )
01544 {
01545   varcode = GRIB_PARAMETER_UNKNOWN;
01546   center = GRIB_CENTER_LOCAL;
01547   subcenter = GRIB_SUBCENTER_LOCAL;
01548   table = GRIB_TABLE_INTERNATIONAL;
01549   process = GRIB_PROCESS_LOCAL;
01550   vals = 0;
01551   size = 0;
01552   varname = "Unknown";
01553   varunit = "Unknown";
01554   vardesc = "Unknown";
01555   numbits = 0;
01556   refvalue = 0.0;
01557   decimalscale = 0;
01558   binscale = 0;
01559   undef_high = 9.9991e20;
01560   undef_low = 9.9991e20;
01561 }
01562 
01563 GRIB_FIELD::~GRIB_FIELD( )
01564 {
01565   if (vals) delete [ ] vals;
01566 }
01567 
01568 void GRIB_FIELD::Decode(unsigned char *pds, unsigned char *bds,
01569                         unsigned char *bms, size_t nxny)
01570 {
01571   if (size != nxny)
01572   {
01573     if (vals) delete [ ] vals;
01574     vals = new float[nxny];
01575   }
01576 
01577   if (vals == 0)
01578     vals = new float[nxny];
01579 
01580   size = nxny;
01581 
01582   center    = PDS_Center(pds);
01583   subcenter = PDS_Subcenter(pds);
01584   table     = PDS_Vsn(pds);
01585   process   = PDS_Model(pds);
01586 
01587   varcode   = PDS_PARAM(pds);
01588 
01589   varname = (Parm_Table(center, subcenter, table, process) + varcode)->name;
01590   vardesc = (Parm_Table(center, subcenter, table, process) + varcode)->comment;
01591   size_t indx0 = vardesc.find_first_of('[', 0);
01592   size_t indx1 = vardesc.find_first_of(']', 0);
01593   varunit = vardesc.substr(indx0+1,indx1-indx0-1);
01594 
01595   numbits = BDS_NumBits(bds);
01596   decimalscale = PDS_DecimalScale(pds);
01597   refvalue = BDS_RefValue(bds);
01598   binscale = BDS_BinScale(bds);
01599 
01600   double temp = int_power(10.0, - decimalscale);
01601 
01602   BDS_unpack(vals, bds, BMS_bitmap(bms), numbits, size,
01603              temp * refvalue, temp * int_power(2.0, binscale));
01604 
01605   return;
01606 }
01607 
01608 std::string GRIB_FIELD::VarName( ) { return varname; }
01609 std::string GRIB_FIELD::VarUnit( ) { return varunit; }
01610 std::string GRIB_FIELD::VarDescription( ) { return vardesc; }
01611 
01612 void GRIB_FIELD::set_table(int c, int s, int t, int p)
01613 {
01614   center = c;
01615   subcenter = s;
01616   table = t;
01617   process = p;
01618   return;
01619 }
01620 
01621 void GRIB_FIELD::set_scale(int scale)
01622 {
01623   decimalscale = scale;
01624   return;
01625 }
01626 
01627 void GRIB_FIELD::set_field(int v, float *values, size_t s, float uh, float ul)
01628 {
01629   varcode = v;
01630   varname = (Parm_Table(center, subcenter, table, process) + varcode)->name;
01631   vardesc = (Parm_Table(center, subcenter, table, process) + varcode)->comment;
01632   size_t indx0 = vardesc.find_first_of('[', 0);
01633   size_t indx1 = vardesc.find_first_of(']', 0);
01634   varunit = vardesc.substr(indx0+1,indx1-indx0-1);
01635   if (size != s || vals == 0)
01636   {
01637     size = s;
01638     if (vals) delete [ ] vals;
01639     vals = new float[s];
01640   }
01641   memcpy(vals, values, s*sizeof(float));
01642   undef_high = uh;
01643   undef_low = ul;
01644   return;
01645 }
01646 
01647 // ############################################################################
01648 // GRIB Message implementation
01649 // ############################################################################
01650 
01651 GRIB_MESSAGE::GRIB_MESSAGE( )
01652 {
01653   message   = 0;
01654   pds       = 0;
01655   gds       = 0;
01656   bms       = 0;
01657   bds       = 0;
01658   reclen    = 0;
01659 }
01660 
01661 GRIB_MESSAGE::~GRIB_MESSAGE( ) { if (message) delete [ ] message; }
01662 
01663 int GRIB_MESSAGE::Decode(unsigned char *msg, size_t msgsize)
01664 {
01665   if (message) delete [ ] message;
01666 
01667   unsigned char *pnt;
01668 
01669   message = new unsigned char[msgsize];
01670   memcpy(message, msg, msgsize);
01671   reclen = msgsize;
01672 
01673   pds = message + 8;
01674   pnt = pds + PDS_LEN(pds);
01675   if (PDS_HAS_GDS(pds))
01676   {
01677     gds = pnt;
01678     pnt += GDS_LEN(gds);
01679   }
01680   if (PDS_HAS_BMS(pds))
01681   {
01682     bms = pnt;
01683     pnt += BMS_LEN(bms);
01684   }
01685   bds = pnt;
01686   pnt += BDS_LEN(bds);
01687 
01688   if ((size_t) (pnt-message+4) != reclen)
01689   {
01690     std::cerr << "Message GRIB lenght is inconsistent" << std::endl;
01691     return -1;
01692   }
01693 
01694   gtime.Decode(pds);
01695   level.Decode(pds);
01696   grid.Decode(pds, gds, bms, bds);
01697   field.Decode(pds, bds, bms, (size_t) grid.nxny);
01698 
01699   return 0;
01700 }
01701 
01702 void GRIB_MESSAGE::Encode( )
01703 {
01704   static unsigned char header[8]  = {'G', 'R', 'I', 'B', ' ', ' ', ' ', '\1'};
01705   static unsigned char trailer[4] = {'7', '7', '7', '7'};
01706 
01707   unsigned char *tenc = gtime.Encode( );
01708   size_t pdslen = 0, gdslen = 0, bmslen = 0, bdslen = 0;
01709 
01710   if (grid.grid_code == 0)
01711   {
01712     std::cerr << "Undefined GRID !" << std::endl;
01713     throw;
01714   }
01715 
01716   if (level.type == GRIB_LEVEL_UNKNOWN)
01717   {
01718     std::cerr << "Undefined LEVEL !" << std::endl;
01719     throw;
01720   }
01721 
01722   if (gtime.timeunit == GRIB_TIMEUNIT_UNKNOWN)
01723   {
01724     std::cerr << "Undefined TIME !" << std::endl;
01725     throw;
01726   }
01727 
01728   if (field.varcode == GRIB_PARAMETER_UNKNOWN)
01729   {
01730     std::cerr << "Undefined FIELD !" << std::endl;
01731     throw;
01732   }
01733 
01734   pds = mk_PDS(NULL, WGRIB_ENCODE_INIT, 28, 0,
01735                WGRIB_ENCODE_BYTE,     3, field.table,
01736                WGRIB_ENCODE_BYTE,     4, field.center,
01737                WGRIB_ENCODE_BYTE,     5, field.process,
01738                WGRIB_ENCODE_BYTE,     6, grid.grid_code,
01739                WGRIB_ENCODE_BYTE,     8, field.varcode,
01740                WGRIB_ENCODE_BYTE,     9, level.type,
01741                WGRIB_ENCODE_2BYTES,  10, level.Encode( ),
01742                WGRIB_ENCODE_BYTE,    12, tenc[0],
01743                WGRIB_ENCODE_BYTE,    13, tenc[1],
01744                WGRIB_ENCODE_BYTE,    14, tenc[2],
01745                WGRIB_ENCODE_BYTE,    15, tenc[3],
01746                WGRIB_ENCODE_BYTE,    16, tenc[4],
01747                WGRIB_ENCODE_BYTE,    17, tenc[5],
01748                WGRIB_ENCODE_BYTE,    18, tenc[6],
01749                WGRIB_ENCODE_BYTE,    19, tenc[7],
01750                WGRIB_ENCODE_BYTE,    20, tenc[8],
01751                WGRIB_ENCODE_BYTE,    21, tenc[9],
01752                WGRIB_ENCODE_BYTE,    22, tenc[10],
01753                WGRIB_ENCODE_BYTE,    23, tenc[11],
01754                WGRIB_ENCODE_BYTE,    24, tenc[12],
01755                WGRIB_ENCODE_BYTE,    25, field.subcenter,
01756                WGRIB_ENCODE_S2BYTES, 26, field.decimalscale,
01757                WGRIB_ENCODE_END);
01758 
01759   pdslen = PDS_LEN(pds);
01760 
01761   gds = grid.Encode( );
01762   if (gds)
01763   {
01764     pds[7] |= 128;              // GDS is included
01765     gdslen = GDS_LEN(gds);
01766   }
01767 
01768   int mask_nxny = field.size;
01769   float *tocomp = new float[field.size];
01770   memcpy(tocomp, field.vals, field.size*sizeof(float));
01771 
01772   // Create bitmask
01773   bms = mk_BMS(pds, tocomp, &mask_nxny, field.undef_low, field.undef_high);
01774   if (bms)
01775     bmslen = BMS_LEN(bms);
01776 
01777   bds = mk_BDS(pds, tocomp, mask_nxny);
01778   bdslen = BDS_LEN(bds);
01779 
01780   delete [ ] tocomp;
01781 
01782   reclen = pdslen + gdslen + bmslen + bdslen + 12;
01783 
01784   header[4] = (reclen >> 16) & 255;
01785   header[5] = (reclen >>  8) & 255;
01786   header[6] = (reclen      ) & 255;
01787 
01788   if (message) delete [ ] message;
01789   message = new unsigned char[reclen];
01790 
01791   size_t lpos = 0;
01792   memcpy(message, header, 8*sizeof(unsigned char));
01793   lpos += 8;
01794   memcpy(message+lpos, pds, pdslen*sizeof(unsigned char));
01795   free(pds);
01796   pds = message+lpos;
01797   lpos += pdslen;
01798   if (gds)
01799   {
01800     memcpy(message+lpos, gds, gdslen*sizeof(unsigned char));
01801     free(gds);
01802     gds = message+lpos;
01803     lpos += gdslen;
01804   }
01805   if (bms)
01806   {
01807     memcpy(message+lpos, bms, bmslen*sizeof(unsigned char));
01808     free(bms);
01809     bms = message+lpos;
01810     lpos += bmslen;
01811   }
01812   memcpy(message+lpos, bds, bdslen*sizeof(unsigned char));
01813   free(bds);
01814   bds = message+lpos;
01815   lpos += bdslen;
01816  
01817   memcpy(message+lpos, trailer, 4*sizeof(unsigned char));
01818   lpos += 4;
01819 
01820   if (reclen != lpos) throw;
01821 
01822   return;
01823 }
01824 
01825 void GRIB_MESSAGE::set_grid(GRIB_GRID &g)
01826 {
01827   grid.grid_code = g.grid_code;
01828   grid.type = g.type;
01829   grid.nxny = g.nxny;
01830   grid.nx = g.nx;
01831   grid.ny = g.ny;
01832   grid.is_dirincgiven = g.is_dirincgiven;
01833   grid.is_earth_spheroid = g.is_earth_spheroid;
01834   grid.is_uv_grid = g.is_uv_grid;
01835   grid.is_x_negative = g.is_x_negative;
01836   grid.is_y_negative = g.is_y_negative;
01837   grid.is_fortran = g.is_fortran;
01838   switch (g.type)
01839   {
01840     case GRIB_GRID_REGULAR_LATLON:
01841       grid.ll.lat1 = g.ll.lat1;
01842       grid.ll.lon1 = g.ll.lon1;
01843       grid.ll.lat2 = g.ll.lat2;
01844       grid.ll.lon2 = g.ll.lon2;
01845       grid.ll.dlat = g.ll.dlat;
01846       grid.ll.dlon = g.ll.dlon;
01847       break;
01848     case GRIB_GRID_GAUSSIAN:
01849       grid.gl.lat1 = g.gl.lat1;
01850       grid.gl.lon1 = g.gl.lon1;
01851       grid.gl.lat2 = g.gl.lat2;
01852       grid.gl.lon2 = g.gl.lon2;
01853       grid.gl.dlon = g.gl.dlon;
01854       grid.gl.N    = g.gl.N;
01855       break;
01856     case GRIB_GRID_POLAR_STEREOGRAPHIC:
01857       grid.ps.lat1 = g.ps.lat1;
01858       grid.ps.lon1 = g.ps.lon1;
01859       grid.ps.lov  = g.ps.lov;
01860       grid.ps.dx   = g.ps.dx;
01861       grid.ps.dy   = g.ps.dy;
01862       grid.ps.pole = g.ps.pole;
01863       break;
01864     case GRIB_GRID_LAMBERT_CONFORMAL:
01865       grid.lc.lat1    = g.lc.lat1;
01866       grid.lc.lon1    = g.lc.lon1;
01867       grid.lc.lov     = g.lc.lov;
01868       grid.lc.latin1  = g.lc.latin1;
01869       grid.lc.latin2  = g.lc.latin2;
01870       grid.lc.latsp   = g.lc.latsp;
01871       grid.lc.lonsp   = g.lc.lonsp;
01872       grid.lc.dx      = g.lc.dx;
01873       grid.lc.dy      = g.lc.dy;
01874       grid.lc.pole    = g.lc.pole;
01875       grid.lc.bipolar = g.lc.bipolar;
01876       break;
01877     case GRIB_GRID_MERCATOR:
01878       grid.mc.lat1  = g.mc.lat1;
01879       grid.mc.lon1  = g.mc.lon1;
01880       grid.mc.lat2  = g.mc.lat2;
01881       grid.mc.lon2  = g.mc.lon2;
01882       grid.mc.dx    = g.mc.dx;
01883       grid.mc.dy    = g.mc.dy;
01884       grid.mc.latin = g.mc.latin;
01885       break;
01886     case GRIB_GRID_SPHERICAL_HARMONIC_COE:
01887       grid.sa.J  = g.sa.J;
01888       grid.sa.K  = g.sa.K;
01889       grid.sa.M  = g.sa.M;
01890               grid.sa.representation = g.sa.representation;
01891       grid.sa.storage_method = g.sa.storage_method;
01892       break;
01893     case GRIB_GRID_SPACEVIEW:
01894       grid.sp.lap  = g.sp.lap;
01895       grid.sp.lop  = g.sp.lop;
01896       grid.sp.dx  = g.sp.dx;
01897       grid.sp.dy  = g.sp.dy;
01898       grid.sp.Xp  = g.sp.Xp;
01899       grid.sp.Yp  = g.sp.Yp;
01900       grid.sp.orient  = g.sp.orient;
01901       grid.sp.Nr  = g.sp.Nr;
01902       break;
01903     default:
01904       break;
01905   }
01906   return;
01907 }
01908 
01909 void GRIB_MESSAGE::set_time(GRIB_TIME &t)
01910 {
01911   gtime.reftime = t.reftime;
01912   gtime.timestring = t.timestring;
01913   gtime.year = t.year;
01914   gtime.month = t.month;
01915   gtime.day = t.day;
01916   gtime.hour = t.hour;
01917   gtime.minute = t.minute;
01918   gtime.p1 = t.p1;
01919   gtime.p2 = t.p2;
01920   gtime.p1p2 = t.p1p2;
01921   gtime.naveraged = t.naveraged;
01922   gtime.nmissing = t.nmissing;
01923   gtime.timeunit = t.timeunit;
01924   gtime.timerange = t.timerange;
01925   return;
01926 }
01927 
01928 void GRIB_MESSAGE::set_level(GRIB_LEVEL &l)
01929 {
01930   level.type = l.type;
01931   level.lv1 = l.lv1;
01932   level.lv2 = l.lv2;
01933   return;
01934 }
01935 
01936 void GRIB_MESSAGE::set_field(GRIB_FIELD &f)
01937 {
01938   if (field.vals) delete [ ] field.vals;
01939   field.vals = 0;
01940   field.size = 0;
01941 
01942   if (f.size)
01943   {
01944     field.size = f.size;
01945     field.vals = new float[f.size];
01946     memcpy(field.vals, f.vals, f.size*sizeof(float));
01947   }
01948   else
01949     field.vals = 0;
01950 
01951   field.varcode = f.varcode;
01952   field.varname = f.varname;
01953   field.varunit = f.varunit;
01954   field.vardesc = f.vardesc;
01955   field.numbits = f.numbits;
01956   field.refvalue = f.refvalue;
01957   field.decimalscale = f.decimalscale;
01958   field.binscale = f.binscale;
01959   field.undef_high = f.undef_high;
01960   field.undef_low = f.undef_low;
01961   return;
01962 }
01963 
01964 
01965 // ############################################################################
01966 // GRIB File outer interface
01967 // ############################################################################
01968 
01969 GRIB_FILE::GRIB_FILE( )
01970 {
01971   pos     = 0;
01972   size    = 0;
01973   limit   = 0;
01974   data    = 0;
01975   fd      = -1;
01976 }
01977 
01978 int GRIB_FILE::OpenRead(char *fname)
01979 {
01980   struct stat finfo;
01981 
01982   if (stat(fname, &finfo) < 0)
01983   {
01984     std::cerr << "Error opening input file " << fname << std::endl;
01985     return -1;
01986   }
01987 
01988   size = finfo.st_size;
01989   limit = size-4;
01990 
01991   fd = open(fname, O_RDONLY);
01992   if (fd < 0)
01993   {
01994     std::cerr << "Error opening input file " << fname << std::endl;
01995     return -1;
01996   }
01997 
01998   data = (unsigned char *) mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0);
01999   if (data == MAP_FAILED)
02000   {
02001     std::cerr << "Error reading input file " << fname << std::endl;
02002     return -1;
02003   }
02004 
02005   return 0;
02006 }
02007 
02008 int GRIB_FILE::OpenRead(std::string fname)
02009 {
02010   return this->OpenRead(fname.c_str( ));
02011 }
02012 
02013 int GRIB_FILE::OpenWrite(char *fname)
02014 {
02015   fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
02016   if (fd < 0)
02017   {
02018     std::cerr << "Error opening output file " << fname << std::endl;
02019     return -1;
02020   }
02021 
02022   return 0;
02023 }
02024 
02025 int GRIB_FILE::OpenWrite(std::string fname)
02026 {
02027   return this->OpenWrite(fname.c_str( ));
02028 }
02029 
02030 int GRIB_FILE::Append(char *fname)
02031 {
02032   fd = open(fname, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
02033   if (fd < 0)
02034   {
02035     std::cerr << "Error opening output file " << fname << std::endl;
02036     return -1;
02037   }
02038 
02039   return 0;
02040 }
02041 
02042 int GRIB_FILE::Append(std::string fname)
02043 {
02044   return this->Append(fname.c_str( ));
02045 }
02046 
02047 int GRIB_FILE::Close( )
02048 {
02049   if (data) munmap(data, size);
02050   if (fd > 0) close(fd);
02051   pos     = 0;
02052   size    = 0;
02053   limit   = 0;
02054   data    = 0;
02055   fd      = -1;
02056   return 0;
02057 }
02058 
02059 GRIB_FILE::~GRIB_FILE( ) { (void) this->Close( ); }
02060 
02061 int GRIB_FILE::ReadMessage(GRIB_MESSAGE &message)
02062 {
02063   size_t reclen = 0;
02064 
02065   if (pos >= limit)
02066     return 1;
02067 
02068   char *cpnt = (char *) data;
02069 
02070   while (pos < limit)
02071   {
02072     if (*(cpnt+pos)   == 'G' &&
02073         *(cpnt+pos+1) == 'R' &&
02074         *(cpnt+pos+2) == 'I' &&
02075         *(cpnt+pos+3) == 'B') break;
02076     ++pos;
02077   }
02078 
02079   if (pos >= limit)
02080     return 1;
02081 
02082   unsigned char *msg = data+pos;
02083 
02084   reclen = (msg[4]<<16) + (msg[5]<<8) + msg[6];
02085 
02086   if (msg[7] != 1)
02087   {
02088     std::cerr << "Message GRIB version is not 1: " << (int) msg[7]
02089               << std::endl;
02090     return -1;
02091   }
02092 
02093   pos = pos + reclen;
02094   return message.Decode(msg, reclen);
02095 }
02096 
02097 int GRIB_FILE::WriteMessage(GRIB_MESSAGE &msg)
02098 {
02099   size_t wbytes;
02100 
02101   msg.Encode( );
02102   if (msg.message == 0) throw;
02103 
02104   wbytes = write(fd, (void *) msg.message, msg.reclen);
02105   if (wbytes != msg.reclen)
02106   {
02107     std::cerr << "Error writing output message !" << std::endl;
02108     throw;
02109   }
02110 
02111   return 0;
02112 }
02113 
02114 #ifdef TESTME
02115 
02116 int main(int argc, char *argv[])
02117 {
02118   if (argc < 2) return -1;
02119 
02120   GRIB_FILE gf;
02121   GRIB_FILE gn;
02122 
02123   int ret = gf.OpenRead(argv[1]);
02124   if (ret != 0) return -1;
02125 
02126   GRIB_MESSAGE m;
02127 
02128   while ((ret = gf.ReadMessage(m)) == 0)
02129   {
02130     std::cout << "Message:  " << m.field.VarDescription( ) << std::endl;
02131     std::cout << "Grid :    " << m.grid << std::endl
02132               << "Level:    " << m.level << std::endl
02133               << "Time :    " << m.gtime << std::endl << std::endl;
02134 
02135   }
02136 
02137   if (ret < 0) return -1;
02138 
02139   ret = gf.Close( );
02140   if (ret != 0) return -1;
02141 
02142   GRIB_MESSAGE m1;
02143   GRIB_GRID g;
02144   GRIB_LEVEL l;
02145   GRIB_TIME t;
02146   GRIB_FIELD f; 
02147 
02148   ret = gn.OpenWrite("outtest.grb");
02149   if (ret != 0) return -1;
02150 
02151   float *ff = new float[65160];
02152   for (int i = 0; i < 65160; i ++)
02153     ff[i] = 273.15 + i/360;
02154 
02155   // set time
02156   t.set_referencetime(2004, 7, 3, 12, 0);
02157   t.set_forecast_hour(12);
02158 
02159   // set level
02160   l.set_pressure(1000.0);
02161 
02162   // set grid
02163   g.set_size(360, 181);
02164   g.set_regular_latlon(90.0, -90.0, 0.0, -1.0, 1.0, 1.0);
02165 
02166   // set field values
02167   f.set_field(GRIB_PARAMETER_TMP__, ff, 65160, 9.9991e20, 9.9991e20);
02168 
02169   m1.set_time(t);
02170   m1.set_grid(g);
02171   m1.set_level(l);
02172   m1.set_field(f);
02173 
02174   gn.WriteMessage(m1);
02175 
02176   for (int i = 0; i < 65160; i ++)
02177     ff[i] = 10000 + i/360;
02178 
02179   f.set_field(GRIB_PARAMETER_PRES_, ff, 65160, 9.9991e20, 9.9991e20);
02180 
02181   m1.set_field(f);
02182 
02183   gn.WriteMessage(m1);
02184 
02185   ret = gn.Close( );
02186   if (ret != 0) return -1;
02187 
02188   delete [ ] ff;
02189 
02190   std::cout << "Done." << std::endl;
02191   return 0;
02192 }
02193 
02194 #endif

Generated on Fri Sep 10 09:52:07 2004 for GRIBLIB by doxygen1.2.18