示例#1
0
void GRIBDataset::SetGribMetaData(grib_MetaData* meta)
{
    nRasterXSize = meta->gds.Nx;
    nRasterYSize = meta->gds.Ny;

/* -------------------------------------------------------------------- */
/*      Image projection.                                               */
/* -------------------------------------------------------------------- */
    OGRSpatialReference oSRS;

    switch(meta->gds.projType)
    {
      case GS3_LATLON:
      case GS3_GAUSSIAN_LATLON:
          // No projection, only latlon system (geographic)
          break;
      case GS3_MERCATOR:
        oSRS.SetMercator(meta->gds.meshLat, meta->gds.orientLon,
                         1.0, 0.0, 0.0);
        break;
      case GS3_POLAR:
        oSRS.SetPS(meta->gds.meshLat, meta->gds.orientLon,
                   meta->gds.scaleLat1,
                   0.0, 0.0);
        break;
      case GS3_LAMBERT:
        oSRS.SetLCC(meta->gds.scaleLat1, meta->gds.scaleLat2,
                    0.0, meta->gds.orientLon,
                    0.0, 0.0); // set projection
        break;
			

      case GS3_ORTHOGRAPHIC:

        //oSRS.SetOrthographic(0.0, meta->gds.orientLon,
        //											meta->gds.lon2, meta->gds.lat2);
        //oSRS.SetGEOS(meta->gds.orientLon, meta->gds.stretchFactor, meta->gds.lon2, meta->gds.lat2);
        oSRS.SetGEOS(  0, 35785831, 0, 0 ); // hardcoded for now, I don't know yet how to parse the meta->gds section
        break;
      case GS3_EQUATOR_EQUIDIST:
        break;
      case GS3_AZIMUTH_RANGE:
        break;
    }

/* -------------------------------------------------------------------- */
/*      Earth model                                                     */
/* -------------------------------------------------------------------- */
    double a = meta->gds.majEarth * 1000.0; // in meters
    double b = meta->gds.minEarth * 1000.0;
    if( a == 0 && b == 0 )
    {
        a = 6377563.396;
        b = 6356256.910;
    }

    if (meta->gds.f_sphere)
    {
        oSRS.SetGeogCS( "Coordinate System imported from GRIB file",
                        NULL,
                        "Sphere",
                        a, 0.0 );
    }
    else
    {
        double fInv = a/(a-b);
        oSRS.SetGeogCS( "Coordinate System imported from GRIB file",
                        NULL,
                        "Spheroid imported from GRIB file",
                        a, fInv );
    }

    OGRSpatialReference oLL; // construct the "geographic" part of oSRS
    oLL.CopyGeogCSFrom( &oSRS );

    double rMinX;
    double rMaxY;
    double rPixelSizeX;
    double rPixelSizeY;
    if (meta->gds.projType == GS3_ORTHOGRAPHIC)
    {
        //rMinX = -meta->gds.Dx * (meta->gds.Nx / 2); // This is what should work, but it doesn't .. Dx seems to have an inverse relation with pixel size
        //rMaxY = meta->gds.Dy * (meta->gds.Ny / 2);
        const double geosExtentInMeters = 11137496.552; // hardcoded for now, assumption: GEOS projection, full disc (like MSG)
        rMinX = -(geosExtentInMeters / 2);
        rMaxY = geosExtentInMeters / 2;
        rPixelSizeX = geosExtentInMeters / meta->gds.Nx;
        rPixelSizeY = geosExtentInMeters / meta->gds.Ny;
    }
    else if( oSRS.IsProjected() )
    {
        rMinX = meta->gds.lon1; // longitude in degrees, to be transformed to meters (or degrees in case of latlon)
        rMaxY = meta->gds.lat1; // latitude in degrees, to be transformed to meters 
        OGRCoordinateTransformation *poTransformLLtoSRS = OGRCreateCoordinateTransformation( &(oLL), &(oSRS) );
        if ((poTransformLLtoSRS != NULL) && poTransformLLtoSRS->Transform( 1, &rMinX, &rMaxY )) // transform it to meters
        {
            if (meta->gds.scan == GRIB2BIT_2) // Y is minY, GDAL wants maxY
                rMaxY += (meta->gds.Ny - 1) * meta->gds.Dy; // -1 because we GDAL needs the coordinates of the centre of the pixel
            rPixelSizeX = meta->gds.Dx;
            rPixelSizeY = meta->gds.Dy;
        }
        else
        {
            rMinX = 0.0;
            rMaxY = 0.0;
            
            rPixelSizeX = 1.0;
            rPixelSizeY = -1.0;
            
            oSRS.Clear();

            CPLError( CE_Warning, CPLE_AppDefined,
                      "Unable to perform coordinate transformations, so the correct\n"
                      "projected geotransform could not be deduced from the lat/long\n"
                      "control points.  Defaulting to ungeoreferenced." );
        }
        delete poTransformLLtoSRS;
    }
    else
    {
        rMinX = meta->gds.lon1; // longitude in degrees, to be transformed to meters (or degrees in case of latlon)
        rMaxY = meta->gds.lat1; // latitude in degrees, to be transformed to meters 

        if (meta->gds.lat2 > rMaxY)
          rMaxY = meta->gds.lat2;
        rPixelSizeX = meta->gds.Dx;
        rPixelSizeY = meta->gds.Dy;
    }

    adfGeoTransform[0] = rMinX;
    adfGeoTransform[3] = rMaxY;
    adfGeoTransform[1] = rPixelSizeX;
    adfGeoTransform[5] = -rPixelSizeY;

    CPLFree( pszProjection );
    pszProjection = NULL;
    oSRS.exportToWkt( &(pszProjection) );
}
rspfString rspfOgcWktTranslator::fromOssimKwl(const rspfKeywordlist &kwl,
                                                const char *prefix)const
{
   rspfString projType = kwl.find(rspfKeywordNames::TYPE_KW);
   rspfString datumType = kwl.find(rspfKeywordNames::DATUM_KW);
   
   rspfString wktString;
   OGRSpatialReference oSRS;
   
   if(projType == "")
   {
      return wktString;
   }
   
   rspfString zone = kwl.find(prefix, rspfKeywordNames::ZONE_KW);
   rspfString hemisphere = kwl.find(prefix, rspfKeywordNames::HEMISPHERE_KW);
   rspfString parallel1  = kwl.find(prefix, rspfKeywordNames::STD_PARALLEL_1_KW);
   rspfString parallel2  = kwl.find(prefix, rspfKeywordNames::STD_PARALLEL_2_KW);
   rspfString originLat  = kwl.find(prefix, rspfKeywordNames::ORIGIN_LATITUDE_KW);
   rspfString centralMeridian = kwl.find(prefix, rspfKeywordNames::CENTRAL_MERIDIAN_KW);
   rspfString scale = kwl.find(prefix, rspfKeywordNames::SCALE_FACTOR_KW);
   rspfString pcsCode = kwl.find(prefix, rspfKeywordNames::PCS_CODE_KW);
   rspfDpt falseEastingNorthing;
   falseEastingNorthing.x = 0.0;
   falseEastingNorthing.y = 0.0;
   const char *lookup =
      kwl.find(prefix, rspfKeywordNames::FALSE_EASTING_NORTHING_UNITS_KW);
   if (lookup)
   {
      rspfUnitType units =
         static_cast<rspfUnitType>(rspfUnitTypeLut::instance()->
                                    getEntryNumber(lookup));
      
      lookup = kwl.find(prefix, rspfKeywordNames::FALSE_EASTING_NORTHING_KW);
      if (lookup)
      {
         rspfDpt eastingNorthing;
         eastingNorthing.toPoint(std::string(lookup));
         
         switch (units)
         {
            case RSPF_METERS:
            {
               falseEastingNorthing = eastingNorthing;
               break;
            }
            case RSPF_FEET:
            case RSPF_US_SURVEY_FEET:
            {
               rspfUnitConversionTool ut;
               ut.setValue(eastingNorthing.x, units);
               falseEastingNorthing.x = ut.getValue(RSPF_METERS);
               ut.setValue(eastingNorthing.y, units);
               falseEastingNorthing.y = ut.getValue(RSPF_METERS);
               break;
            }
            default:
            {
               rspfNotify(rspfNotifyLevel_WARN)
                  << "rspfOgcWktTranslator::fromOssimKwl WARNING!"
                  << "Unhandled unit type for "
                  << rspfKeywordNames::FALSE_EASTING_NORTHING_UNITS_KW
                  << ":  " 
                  << ( rspfUnitTypeLut::instance()->
                       getEntryString(units).c_str() )
                  << endl;
               break;
            }
         } // End of switch (units)
         
      }  // End of if (FALSE_EASTING_NORTHING_KW)
   } // End of if (FALSE_EASTING_NORTHING_UNITS_KW)
   else
   {
      lookup =  kwl.find(prefix, rspfKeywordNames::FALSE_EASTING_KW);
      if(lookup)
      {
         falseEastingNorthing.x = fabs(rspfString(lookup).toFloat64());
      }
      
      lookup =  kwl.find(prefix, rspfKeywordNames::FALSE_NORTHING_KW);
      if(lookup)
      {
         falseEastingNorthing.y = fabs(rspfString(lookup).toFloat64());
      }
   }
   oSRS.SetLinearUnits("Meter", 1.0);
   int pcsCodeVal = (pcsCode.empty() == false) ? pcsCode.toInt() : EPSG_CODE_MAX;
   if(pcsCodeVal < EPSG_CODE_MAX)
   {
      rspfEpsgProjectionDatabase* proj_db = rspfEpsgProjectionDatabase::instance();
      rspfString pcsCodeName = proj_db->findProjectionName(pcsCodeVal);
      if ( pcsCodeName.contains("HARN") && pcsCodeName.contains("_Feet") )
      {
         rspfString feetStr("_Feet");
         rspfString newPcsCodeName( pcsCodeName.before(feetStr).c_str() );
         rspfString epsg_spec = proj_db->findProjectionCode(newPcsCodeName);
         rspf_uint32 new_code = epsg_spec.after(":").toUInt32();
         if (new_code)
          pcsCodeVal = new_code;
      }
      oSRS.importFromEPSG( pcsCodeVal );
   }
   else if(projType == "rspfUtmProjection")
   {
#if 0
      hemisphere = hemisphere.trim().upcase();
      
      if(hemisphere != "")
      {
         oSRS.SetUTM(zone.toLong(), hemisphere != "S");
      }
      else
      {
         oSRS.SetUTM(zone.toLong(), true);
      }
#else
      short gcs = USER_DEFINED;
      if (datumType == "WGE") gcs = GCS_WGS_84;
      else if (datumType == "WGD") gcs = GCS_WGS_72;
      else if (datumType == "NAR-C") gcs = GCS_NAD83;
      else if (datumType == "NAR") gcs = GCS_NAD83;
      else if (datumType == "NAS-C") gcs = GCS_NAD27;
      else if (datumType == "NAS") gcs = GCS_NAD27;
      else if (datumType == "ADI-M") gcs = GCS_Adindan;
      else if (datumType == "ARF-M") gcs = GCS_Arc_1950;
      else if (datumType == "ARS-M") gcs = GCS_Arc_1960;
      else if (datumType == "EUR-7" || datumType == "EUR-M") gcs = GCS_ED50;
      else if ((datumType == "OGB-7") ||
               (datumType == "OGB-M") ||
               (datumType == "OGB-A") ||
               (datumType == "OGB-B") ||
               (datumType == "OGB-C") ||
               (datumType == "OGB-D")) gcs = GCS_OSGB_1936;
      else if  (datumType == "TOY-M")  gcs = GCS_Tokyo;
      else
      {
         if(traceDebug())
         {
            rspfNotify(rspfNotifyLevel_DEBUG)
               << "DATUM = " << datumType << " tag not written " << std::endl
               << "Please let us know so we can add it"          << std::endl;
         }
      }
      int mapZone = zone.toInt();
      hemisphere = hemisphere.trim().upcase();
      bool bDoImportFromEPSG = false;
      switch ( gcs )
      {
         case GCS_WGS_84:
         {
            if (hemisphere == "N") // Northern hemisphere.
            {
               pcsCodeVal = 32600 + mapZone;
            }
            else // Southern hemisphere.
            {
               pcsCodeVal = 32700 + mapZone;
            }
            bDoImportFromEPSG = true;
            break;
         }
         case GCS_WGS_72:
         {
            if (hemisphere == "N") // Northern hemisphere.
            {
               pcsCodeVal = 32200 + mapZone;
            }
            else // Southern hemisphere.
            {
               pcsCodeVal = 32300 + mapZone;
            }
            bDoImportFromEPSG = true;
            break;
         }
         case GCS_NAD27:
         {
            if (hemisphere == "N") // Northern hemisphere.
            {
               pcsCodeVal = 26700 + mapZone;
            }
            else // Southern hemisphere.
            {
               pcsCodeVal = 32000 + mapZone;
            }
            bDoImportFromEPSG = true;
            break;
         }
         case GCS_NAD83:
         {
            if (hemisphere == "N") // Northern hemisphere.
            {
               pcsCodeVal = 26900 + mapZone;
            }
            else // Southern hemisphere.
            {
               pcsCodeVal = 32100 + mapZone;
            }
            bDoImportFromEPSG = true;
            break;
         }
         default:
         {
            if (mapZone > 0) // Northern hemisphere.
            {
               pcsCodeVal = 16000 + mapZone;
            }
            else if (mapZone < 0) // Southern hemisphere.
            {
               hemisphere = "S";
               pcsCodeVal = 16100 + abs(mapZone);
            }
            break;
         }
      } // End of "switch ( gcs )"
      if ( bDoImportFromEPSG == true )
         oSRS.importFromEPSG( pcsCodeVal );
      else
      {
         if(hemisphere != "")
         {
            oSRS.SetUTM(zone.toLong(), hemisphere != "S");
         }
         else
         {
            oSRS.SetUTM(zone.toLong(), true);
         }
      }
#endif
   }
   else if(projType == "rspfLlxyProjection")
   {
      OGRSpatialReference oGeogCS;
      
      oGeogCS.SetEquirectangular(0.0,
                                 0.0,
                                 0.0,
                                 0.0);
      oGeogCS.SetAngularUnits(SRS_UA_DEGREE, atof(SRS_UA_DEGREE_CONV));
      
      oSRS.CopyGeogCSFrom( &oGeogCS );  
   }
   else if(projType == "rspfEquDistCylProjection")
   {
      OGRSpatialReference oGeogCS;
      
      oGeogCS.SetEquirectangular(originLat.toDouble(),
                                 centralMeridian.toDouble(),
                                 falseEastingNorthing.x,
                                 falseEastingNorthing.y);
      oGeogCS.SetAngularUnits(SRS_UA_DEGREE, atof(SRS_UA_DEGREE_CONV));
      
      oSRS.CopyGeogCSFrom( &oGeogCS );  
   }
   else if(projType == "rspfSinusoidalProjection")
   {
      oSRS.SetSinusoidal(centralMeridian.toDouble(),
                         falseEastingNorthing.x,
                         falseEastingNorthing.y);
   }
   else if(projType == "rspfCylEquAreaProjection")
   {
      oSRS.SetCEA(originLat.toDouble(),
                  centralMeridian.toDouble(),
                  falseEastingNorthing.x,
                  falseEastingNorthing.y);
   }
   else if(projType == "rspfCassiniProjection")
   {
      oSRS.SetCS(originLat.toDouble(),
                 centralMeridian.toDouble(),
                 falseEastingNorthing.x,
                 falseEastingNorthing.y);
   }
   else if(projType == "rspfAlbersProjection")
   {
      oSRS.SetACEA(parallel1.toDouble(),
                   parallel2.toDouble(),
                   originLat.toDouble(),
                   centralMeridian.toDouble(),
                   falseEastingNorthing.x,
                   falseEastingNorthing.y);
   }
   else if(projType == "rspfAzimEquDistProjection")
   {
      oSRS.SetAE(originLat.toDouble(),
                 centralMeridian.toDouble(),
                 falseEastingNorthing.x,
                 falseEastingNorthing.y);
   }
   else if(projType == "rspfEckert4Projection")
   {
      oSRS.SetEckertIV(centralMeridian.toDouble(),
                       falseEastingNorthing.x,
                       falseEastingNorthing.y);
   }
   else if(projType == "rspfEckert6Projection")
   {
      oSRS.SetEckertVI(centralMeridian.toDouble(),
                       falseEastingNorthing.x,
                       falseEastingNorthing.y);
   }
   else if(projType == "rspfGnomonicProjection")
   {
      oSRS.SetGnomonic(originLat.toDouble(),
                       centralMeridian.toDouble(),
                       falseEastingNorthing.x,
                       falseEastingNorthing.y);
   }
   else if(projType == "rspfLambertConformalConicProjection")
   {
      oSRS.SetLCC(parallel1.toDouble(),
                  parallel2.toDouble(),
                  originLat.toDouble(),
                  centralMeridian.toDouble(),
                  falseEastingNorthing.x,
                  falseEastingNorthing.y);
   }
   else if(projType == "rspfVanDerGrintenProjection")
   {
      oSRS.SetVDG(centralMeridian.toDouble(),
                  falseEastingNorthing.x,
                  falseEastingNorthing.y);
   }
   else if(projType == "rspfMillerProjection")
   {
      oSRS.SetMC(originLat.toDouble(),
                 centralMeridian.toDouble(),
                 falseEastingNorthing.x,
                 falseEastingNorthing.y);
   }
   else if(projType == "rspfMercatorProjection")
   {
      oSRS.SetMercator(originLat.toDouble(),
                       centralMeridian.toDouble(),
                       scale.toDouble(),
                       falseEastingNorthing.x,
                       falseEastingNorthing.y);
   }
   else if(projType == "rspfMollweidProjection")
   {
      oSRS.SetMollweide(centralMeridian.toDouble(),
                        falseEastingNorthing.x,
                        falseEastingNorthing.y);
   }
   else if(projType == "rspfNewZealandMapGridProjection")
   {
      oSRS.SetNZMG(originLat.toDouble(),
                   centralMeridian.toDouble(),
                   falseEastingNorthing.x,
                   falseEastingNorthing.y);
   }
   else if(projType == "rspfOrthoGraphicProjection")
   {
      oSRS.SetOrthographic(originLat.toDouble(),
                           centralMeridian.toDouble(),
                           falseEastingNorthing.x,
                           falseEastingNorthing.y);
   }
   else if(projType == "rspfPolarStereoProjection")
   {
      oSRS.SetPS(originLat.toDouble(),
                 centralMeridian.toDouble(),
                 scale.toDouble(),
                 falseEastingNorthing.x,
                 falseEastingNorthing.y);
   }
   else if(projType == "rspfPolyconicProjectio")
   {
      oSRS.SetPolyconic(originLat.toDouble(),
                        centralMeridian.toDouble(),
                        falseEastingNorthing.x,
                        falseEastingNorthing.y);
   }
   else if(projType == "rspfStereographicProjection")
   {
      oSRS.SetStereographic(originLat.toDouble(),
                            centralMeridian.toDouble(),
                            scale.toDouble(),
                            falseEastingNorthing.x,
                            falseEastingNorthing.y);
   }
   else if(projType == "rspfTransMercatorProjection")
   {
      oSRS.SetTM(originLat.toDouble(),
                 centralMeridian.toDouble(),
                 scale.toDouble(),
                 falseEastingNorthing.x,
                 falseEastingNorthing.y);
   }
   else 
   {
      cerr << "rspfOgcWktTranslator::fromOssimKwl:\n"
           << "Projection translation for "
           << projType
           << " not supported "
           << endl;
   }
   
   if(pcsCodeVal >= EPSG_CODE_MAX)
   {
      datumType =  datumType.upcase();
      
      if(datumType == "WGE")
      {
         oSRS.SetWellKnownGeogCS("WGS84");
      }
      else if(datumType == "WGD")
      {
         oSRS.SetWellKnownGeogCS("WGS72");      
      }
      else if(datumType == "NAS-C") //1927
      {
         oSRS.SetWellKnownGeogCS("NAD27");      
      }
      else if(datumType == "NAS") //1927
      {
         oSRS.SetWellKnownGeogCS("NAD27");      
      }
      else if(datumType == "NAR-C") // 1983
      {
         oSRS.SetWellKnownGeogCS("NAD83");
      }
      else if(datumType == "NAR") // 1983
      {
         oSRS.SetWellKnownGeogCS("NAD83");
      }
      else if(datumType == "NTF")
      {
        oSRS.SetWellKnownGeogCS("EPSG:4275");
      }
      else
      {
         cerr << "rspfOgcWktTranslator::fromOssimKwl: Datum translation for "
              << datumType
              <<" not supported"
              << endl;
      }
   }
   char* exportString = NULL;
   oSRS.exportToWkt(&exportString);
   
   if(exportString)
   {
      wktString = exportString;
      OGRFree(exportString);
   }
   return wktString;
   
}