LCOV - code coverage report
Current view: directory - frmts/tsx - tsxdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 296 22 7.4 %
Date: 2012-12-26 Functions: 21 3 14.3 %

       1                 : /******************************************************************************
       2                 :  * $Id: tsxdataset.cpp 25311 2012-12-15 12:48:14Z rouault $
       3                 :  *
       4                 :  * Project:     TerraSAR-X XML Product Support
       5                 :  * Purpose:     Support for TerraSAR-X XML Metadata files
       6                 :  * Author:      Philippe Vachon <philippe@cowpig.ca>
       7                 :  * Description: This driver adds support for reading metadata and georef data
       8                 :  *              associated with TerraSAR-X products.
       9                 :  *
      10                 :  ******************************************************************************
      11                 :  * Copyright (c) 2007, Philippe Vachon <philippe@cowpig.ca>
      12                 :  *
      13                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      14                 :  * copy of this software and associated documentation files (the "Software"),
      15                 :  * to deal in the Software without restriction, including without limitation
      16                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      17                 :  * and/or sell copies of the Software, and to permit persons to whom the
      18                 :  * Software is furnished to do so, subject to the following conditions:
      19                 :  *
      20                 :  * The above copyright notice and this permission notice shall be included
      21                 :  * in all copies or substantial portions of the Software.
      22                 :  *
      23                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      24                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      25                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      26                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      27                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      28                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      29                 :  * DEALINGS IN THE SOFTWARE.
      30                 :  ****************************************************************************/
      31                 : 
      32                 : #include "gdal_pam.h"
      33                 : #include "cpl_minixml.h"
      34                 : #include "ogr_spatialref.h"
      35                 : 
      36                 : #define MAX_GCPS 5000    //this should be more than enough ground control points
      37                 : 
      38                 : CPL_CVSID("$Id: tsxdataset.cpp 25311 2012-12-15 12:48:14Z rouault $");
      39                 : 
      40                 : CPL_C_START
      41                 : void GDALRegister_TSX(void);
      42                 : CPL_C_END
      43                 : 
      44                 : 
      45                 : enum ePolarization {
      46                 :     HH=0,
      47                 :     HV,
      48                 :     VH,
      49                 :     VV
      50                 : };
      51                 : 
      52                 : enum eProductType {
      53                 :     eSSC = 0,
      54                 :     eMGD,
      55                 :     eEEC,
      56                 :     eGEC,
      57                 :     eUnknown
      58                 : };
      59                 : 
      60                 : /************************************************************************/
      61                 : /* Helper Functions                                                     */
      62                 : /************************************************************************/
      63                 : 
      64                 : /* GetFilePath: return a relative path to a file within an XML node.
      65                 :  * Returns Null on failure
      66                 :  */
      67               0 : const char *GetFilePath(CPLXMLNode *psXMLNode, const char **pszNodeType) {
      68                 :     const char *pszDirectory, *pszFilename;
      69                 : 
      70               0 :     pszDirectory = CPLGetXMLValue( psXMLNode, "file.location.path", "" );
      71               0 :     pszFilename = CPLGetXMLValue( psXMLNode, "file.location.filename", "" );
      72               0 :     *pszNodeType = CPLGetXMLValue (psXMLNode, "type", " " );
      73                 : 
      74               0 :     if (pszDirectory == NULL || pszFilename == NULL) {
      75               0 :         return NULL;
      76                 :     }
      77                 : 
      78               0 :     return CPLFormFilename( pszDirectory, pszFilename, "" );
      79                 : }
      80                 : 
      81                 : /************************************************************************/
      82                 : /* ==================================================================== */
      83                 : /*                                TSXDataset                                 */
      84                 : /* ==================================================================== */
      85                 : /************************************************************************/
      86                 : 
      87                 : class TSXDataset : public GDALPamDataset {
      88                 :     int nGCPCount;
      89                 :     GDAL_GCP *pasGCPList;
      90                 : 
      91                 :     char *pszGCPProjection;
      92                 : 
      93                 :     char *pszProjection;
      94                 :     double adfGeoTransform[6];
      95                 :     bool bHaveGeoTransform;
      96                 : 
      97                 :     eProductType nProduct;
      98                 : public:
      99                 :     TSXDataset();
     100                 :     ~TSXDataset();
     101                 : 
     102                 :     virtual int GetGCPCount();
     103                 :     virtual const char *GetGCPProjection();
     104                 :     virtual const GDAL_GCP *GetGCPs();
     105                 : 
     106                 :     CPLErr GetGeoTransform( double* padfTransform);
     107                 :     const char* GetProjectionRef();
     108                 : 
     109                 :     static GDALDataset *Open( GDALOpenInfo *poOpenInfo );
     110                 :     static int Identify( GDALOpenInfo *poOpenInfo );
     111                 : private:
     112                 :     bool getGCPsFromGEOREF_XML(char *pszGeorefFilename);
     113                 : };
     114                 : 
     115                 : /************************************************************************/
     116                 : /* ==================================================================== */
     117                 : /*                                TSXRasterBand                           */
     118                 : /* ==================================================================== */
     119                 : /************************************************************************/
     120                 : 
     121                 : class TSXRasterBand : public GDALPamRasterBand {
     122                 :     GDALDataset *poBand;
     123                 :     ePolarization ePol;
     124                 : public:
     125                 :     TSXRasterBand( TSXDataset *poDSIn, GDALDataType eDataType,
     126                 :         ePolarization ePol, GDALDataset *poBand );
     127                 :     virtual ~TSXRasterBand();
     128                 : 
     129                 :     virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage );
     130                 : 
     131                 :     static GDALDataset *Open( GDALOpenInfo *poOpenInfo );
     132                 : };
     133                 : 
     134                 : /************************************************************************/
     135                 : /*                            TSXRasterBand                             */
     136                 : /************************************************************************/
     137                 : 
     138               0 : TSXRasterBand::TSXRasterBand( TSXDataset *poDS, GDALDataType eDataType,
     139               0 :                               ePolarization ePol, GDALDataset *poBand )
     140                 : {
     141               0 :     this->poDS = poDS;
     142               0 :     this->eDataType = eDataType;
     143               0 :     this->ePol = ePol;
     144                 : 
     145               0 :     switch (ePol) {
     146                 :         case HH:
     147               0 :             SetMetadataItem( "POLARIMETRIC_INTERP", "HH" );
     148               0 :             break;
     149                 :         case HV:
     150               0 :             SetMetadataItem( "POLARIMETRIC_INTERP", "HV" );
     151               0 :             break;
     152                 :         case VH:
     153               0 :             SetMetadataItem( "POLARIMETRIC_INTERP", "VH" );
     154               0 :             break;
     155                 :         case VV:
     156               0 :             SetMetadataItem( "POLARIMETRIC_INTERP", "VV" );
     157                 :             break;
     158                 :     }
     159                 : 
     160                 : 
     161                 :     /* now setup the actual raster reader */
     162               0 :     this->poBand = poBand;
     163                 : 
     164               0 :     GDALRasterBand *poSrcBand = poBand->GetRasterBand( 1 );
     165               0 :     poSrcBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
     166               0 : }
     167                 : 
     168                 : /************************************************************************/
     169                 : /*                            TSXRasterBand()                           */
     170                 : /************************************************************************/
     171                 : 
     172               0 : TSXRasterBand::~TSXRasterBand() {
     173               0 :     if( poBand != NULL )
     174               0 :         GDALClose( (GDALRasterBandH) poBand );
     175               0 : }
     176                 : 
     177                 : /************************************************************************/
     178                 : /*                             IReadBlock()                             */
     179                 : /************************************************************************/
     180                 : 
     181               0 : CPLErr TSXRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     182                 :                                   void * pImage )
     183                 : {
     184                 :     int nRequestYSize;
     185                 : 
     186                 :     /* Check if the last strip is partial so we can avoid over-requesting */
     187               0 :     if ( (nBlockYOff + 1) * nBlockYSize > nRasterYSize ) {
     188               0 :         nRequestYSize = nRasterYSize - nBlockYOff * nBlockYSize;
     189                 :         memset( pImage, 0, (GDALGetDataTypeSize( eDataType ) / 8) *
     190               0 :             nBlockXSize * nBlockYSize);
     191                 :     }
     192                 :     else {
     193               0 :         nRequestYSize = nBlockYSize;
     194                 :     }
     195                 : 
     196                 :     /* Read Complex Data */
     197               0 :     if ( eDataType == GDT_CInt16 ) {
     198                 :         return poBand->RasterIO( GF_Read, nBlockXOff * nBlockXSize,
     199                 :             nBlockYOff * nBlockYSize, nBlockXSize, nRequestYSize,
     200                 :             pImage, nBlockXSize, nRequestYSize, GDT_CInt16, 1, NULL, 4,
     201               0 :             nBlockXSize * 4, 0 );
     202                 :     }
     203                 :     else { /* Detected Product */
     204                 :         return poBand->RasterIO( GF_Read, nBlockXOff * nBlockXSize,
     205                 :             nBlockYOff * nBlockYSize, nBlockXSize, nRequestYSize,
     206                 :             pImage, nBlockXSize, nRequestYSize, GDT_UInt16, 1, NULL, 2,
     207               0 :             nBlockXSize * 2, 0 );
     208                 :     }
     209                 : }
     210                 : 
     211                 : /************************************************************************/
     212                 : /* ==================================================================== */
     213                 : /*                                TSXDataset                                */
     214                 : /* ==================================================================== */
     215                 : /************************************************************************/
     216                 : 
     217                 : /************************************************************************/
     218                 : /*                             TSXDataset()                             */
     219                 : /************************************************************************/
     220                 : 
     221               0 : TSXDataset::TSXDataset() {
     222               0 :     nGCPCount = 0;
     223               0 :     pasGCPList = NULL;
     224               0 :     pszGCPProjection = CPLStrdup("");
     225               0 :     pszProjection = CPLStrdup("");
     226               0 :     adfGeoTransform[0] = 0.0;
     227               0 :     adfGeoTransform[1] = 1.0;
     228               0 :     adfGeoTransform[2] = 0.0;
     229               0 :     adfGeoTransform[3] = 0.0;
     230               0 :     adfGeoTransform[4] = 0.0;
     231               0 :     adfGeoTransform[5] = 1.0;
     232               0 :     bHaveGeoTransform = FALSE;
     233               0 : }
     234                 : 
     235                 : /************************************************************************/
     236                 : /*                            ~TSXDataset()                             */
     237                 : /************************************************************************/
     238                 : 
     239               0 : TSXDataset::~TSXDataset() {
     240               0 :     FlushCache();
     241                 : 
     242               0 :     CPLFree( pszProjection );
     243                 : 
     244               0 :     CPLFree( pszGCPProjection );
     245               0 :     if( nGCPCount > 0 )
     246                 :     {
     247               0 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     248               0 :         CPLFree( pasGCPList );
     249                 :     }
     250               0 : }
     251                 : 
     252                 : /************************************************************************/
     253                 : /*                              Identify()                              */
     254                 : /************************************************************************/
     255                 : 
     256           12398 : int TSXDataset::Identify( GDALOpenInfo *poOpenInfo )
     257                 : {
     258           12398 :     if (poOpenInfo->fp == NULL || poOpenInfo->nHeaderBytes < 260)
     259                 :     {
     260           11746 :         if( poOpenInfo->bIsDirectory )
     261                 :         {
     262                 :             CPLString osFilename =
     263              42 :                 CPLFormCIFilename( poOpenInfo->pszFilename, CPLGetFilename( poOpenInfo->pszFilename ), "xml" );
     264                 : 
     265                 :             /* Check if the filename contains TSX1_SAR (TerraSAR-X) or TDX1_SAR (TanDEM-X) */
     266              42 :             if (!(EQUALN(CPLGetBasename( osFilename ), "TSX1_SAR", 8) ||
     267                 :                   EQUALN(CPLGetBasename( osFilename ), "TDX1_SAR", 8)))
     268              42 :                 return 0;
     269                 : 
     270                 :             VSIStatBufL sStat;
     271               0 :             if( VSIStatL( osFilename, &sStat ) == 0 )
     272               0 :                 return 1;
     273                 :         }
     274                 : 
     275           11704 :         return 0;
     276                 :     }
     277                 : 
     278                 :     /* Check if the filename contains TSX1_SAR (TerraSAR-X) or TDX1_SAR (TanDEM-X) */
     279             652 :     if (!(EQUALN(CPLGetBasename( poOpenInfo->pszFilename ), "TSX1_SAR", 8) ||
     280                 :           EQUALN(CPLGetBasename( poOpenInfo->pszFilename ), "TDX1_SAR", 8)))
     281             652 :         return 0;
     282                 : 
     283                 :     /* finally look for the <level1Product tag */
     284               0 :     if (!EQUALN((char *)poOpenInfo->pabyHeader, "<level1Product", 14))
     285               0 :         return 0;
     286                 : 
     287               0 :     return 1;
     288                 : }
     289                 : 
     290                 : /************************************************************************/
     291                 : /*                                getGCPsFromGEOREF_XML()               */
     292                 : /*Reads georeferencing information from the TerraSAR-X GEOREF.XML file    */
     293                 : /*and writes the information to the dataset's gcp list and projection     */
     294                 : /*string.                                                                */
     295                 : /*Returns true on success.                                                */
     296                 : /************************************************************************/
     297               0 : bool TSXDataset::getGCPsFromGEOREF_XML(char *pszGeorefFilename)
     298                 : {
     299                 :     //open GEOREF.xml
     300                 :     CPLXMLNode *psGeorefData;
     301               0 :     psGeorefData = CPLParseXMLFile( pszGeorefFilename );
     302               0 :     if (psGeorefData==NULL)
     303               0 :         return false;
     304                 : 
     305                 :     //get the ellipsoid and semi-major, semi-minor axes
     306                 :     CPLXMLNode *psSphere;
     307                 :     const char *pszEllipsoidName;
     308                 :     double minor_axis, major_axis, inv_flattening;
     309               0 :     OGRSpatialReference osr;
     310               0 :     psSphere = CPLGetXMLNode( psGeorefData, "=geoReference.referenceFrames.sphere" );
     311               0 :     if (psSphere!=NULL)
     312                 :     {
     313               0 :         pszEllipsoidName = CPLGetXMLValue( psSphere, "ellipsoidID", "" );
     314               0 :         minor_axis = atof(CPLGetXMLValue( psSphere, "semiMinorAxis", "0.0" ));
     315               0 :         major_axis = atof(CPLGetXMLValue( psSphere, "semiMajorAxis", "0.0" ));
     316                 :         //save datum parameters to the spatial reference
     317               0 :         if ( EQUAL(pszEllipsoidName, "") || minor_axis==0.0 || major_axis==0.0 )
     318                 :         {
     319                 :             CPLError(CE_Warning,CPLE_AppDefined,"Warning- incomplete"
     320               0 :                 " ellipsoid information.  Using wgs-84 parameters.\n");
     321               0 :             osr.SetWellKnownGeogCS( "WGS84" );
     322                 :         }
     323               0 :         else if ( EQUAL( pszEllipsoidName, "WGS84" ) ) {
     324               0 :             osr.SetWellKnownGeogCS( "WGS84" );
     325                 :         }
     326                 :         else {
     327               0 :             inv_flattening = major_axis/(major_axis - minor_axis);
     328               0 :             osr.SetGeogCS( "","",pszEllipsoidName, major_axis, inv_flattening);
     329                 :         }
     330                 :     }
     331                 : 
     332                 :     //get gcps
     333                 :     CPLXMLNode *psNode;
     334               0 :     CPLXMLNode *psGeolocationGrid = CPLGetXMLNode( psGeorefData, "=geoReference.geolocationGrid" );
     335               0 :     if (psGeolocationGrid==NULL)
     336                 :     {
     337               0 :         CPLDestroyXMLNode( psGeorefData );
     338               0 :         return false;
     339                 :     }
     340               0 :     nGCPCount = atoi(CPLGetXMLValue( psGeolocationGrid, "numberOfGridPoints.total", "0" ));
     341                 :     //count the gcps if the given count value is invalid
     342               0 :     if (nGCPCount<=0)
     343                 :     {
     344               0 :         for( psNode = psGeolocationGrid->psChild; psNode != NULL; psNode = psNode->psNext )
     345               0 :             if( EQUAL(psNode->pszValue,"gridPoint") )
     346               0 :                 nGCPCount++ ;
     347                 :     }
     348                 :     //if there are no gcps, fail
     349               0 :     if(nGCPCount<=0)
     350                 :     {
     351               0 :         CPLDestroyXMLNode( psGeorefData );
     352               0 :         return false;
     353                 :     }
     354                 : 
     355                 :     //put some reasonable limits of the number of gcps
     356               0 :     if (nGCPCount>MAX_GCPS )
     357               0 :         nGCPCount=MAX_GCPS;
     358                 :     //allocate memory for the gcps
     359               0 :     pasGCPList = (GDAL_GCP *)CPLCalloc(sizeof(GDAL_GCP),nGCPCount);
     360                 :     //loop through all gcps and set info
     361               0 :     int gcps_allocated = nGCPCount;    //save the number allocated to ensure it does not run off the end of the array
     362               0 :     nGCPCount=0;    //reset to zero and count
     363                 :     //do a check on the grid point to make sure it has lat,long row, and column
     364                 :     //it seems that only SSC products contain row, col - how to map lat long otherwise??
     365                 :     //for now fail if row and col are not present - just check the first and assume the rest are the same
     366               0 :     for( psNode = psGeolocationGrid->psChild; psNode != NULL; psNode = psNode->psNext )
     367                 :     {
     368               0 :          if( !EQUAL(psNode->pszValue,"gridPoint") )
     369               0 :              continue;
     370                 : 
     371               0 :          if (    !strcmp(CPLGetXMLValue(psNode,"col","error"), "error") ||
     372                 :                  !strcmp(CPLGetXMLValue(psNode,"row","error"), "error") ||
     373                 :                  !strcmp(CPLGetXMLValue(psNode,"lon","error"), "error") ||
     374                 :                  !strcmp(CPLGetXMLValue(psNode,"lat","error"), "error"))
     375                 :         {
     376               0 :             CPLDestroyXMLNode( psGeorefData );
     377               0 :             return false;
     378                 :         }
     379                 :     }
     380               0 :     for( psNode = psGeolocationGrid->psChild; psNode != NULL; psNode = psNode->psNext )
     381                 :     {
     382                 :         //break out if the end of the array has been reached
     383               0 :         if (nGCPCount >= gcps_allocated)
     384                 :         {
     385               0 :             CPLError(CE_Warning, CPLE_AppDefined, "GDAL TSX driver: Truncating the number of GCPs.");
     386               0 :             break;
     387                 :         }
     388                 : 
     389                 :          char    szID[32];
     390               0 :          GDAL_GCP   *psGCP = pasGCPList + nGCPCount;
     391                 : 
     392               0 :          if( !EQUAL(psNode->pszValue,"gridPoint") )
     393               0 :              continue;
     394                 : 
     395               0 :          nGCPCount++ ;
     396                 : 
     397               0 :          sprintf( szID, "%d", nGCPCount );
     398               0 :          psGCP->pszId = CPLStrdup( szID );
     399               0 :          psGCP->pszInfo = CPLStrdup("");
     400                 :          psGCP->dfGCPPixel =
     401               0 :              atof(CPLGetXMLValue(psNode,"col","0"));
     402                 :          psGCP->dfGCPLine =
     403               0 :              atof(CPLGetXMLValue(psNode,"row","0"));
     404                 :          psGCP->dfGCPX =
     405               0 :              atof(CPLGetXMLValue(psNode,"lon",""));
     406                 :          psGCP->dfGCPY =
     407               0 :              atof(CPLGetXMLValue(psNode,"lat",""));
     408                 :          //looks like height is in meters - should it be converted so xyz are all on the same scale??
     409               0 :          psGCP->dfGCPZ = 0;
     410                 :              //atof(CPLGetXMLValue(psNode,"height",""));
     411                 :     }
     412                 : 
     413               0 :     CPLFree(pszGCPProjection);
     414               0 :     osr.exportToWkt( &(pszGCPProjection) );
     415                 : 
     416               0 :     CPLDestroyXMLNode( psGeorefData );
     417                 : 
     418               0 :     return true;
     419                 : }
     420                 : 
     421                 : /************************************************************************/
     422                 : /*                                Open()                                */
     423                 : /************************************************************************/
     424                 : 
     425            2305 : GDALDataset *TSXDataset::Open( GDALOpenInfo *poOpenInfo ) {
     426                 : /* -------------------------------------------------------------------- */
     427                 : /*      Is this a TerraSAR-X product file?                              */
     428                 : /* -------------------------------------------------------------------- */
     429            2305 :     if (!TSXDataset::Identify( poOpenInfo ))
     430                 :     {
     431            2305 :         return NULL; /* nope */
     432                 :     }
     433                 : 
     434                 : /* -------------------------------------------------------------------- */
     435                 : /*      Confirm the requested access is supported.                      */
     436                 : /* -------------------------------------------------------------------- */
     437               0 :     if( poOpenInfo->eAccess == GA_Update )
     438                 :     {
     439                 :         CPLError( CE_Failure, CPLE_NotSupported,
     440                 :                   "The TSX driver does not support update access to existing"
     441               0 :                   " datasets.\n" );
     442               0 :         return NULL;
     443                 :     }
     444                 : 
     445               0 :     CPLString osFilename;
     446                 : 
     447               0 :     if( poOpenInfo->bIsDirectory )
     448                 :     {
     449                 :         osFilename =
     450               0 :                 CPLFormCIFilename( poOpenInfo->pszFilename, CPLGetFilename( poOpenInfo->pszFilename ), "xml" );
     451                 :     }
     452                 :     else
     453               0 :         osFilename = poOpenInfo->pszFilename;
     454                 : 
     455                 :     /* Ingest the XML */
     456                 :     CPLXMLNode *psData, *psComponents, *psProductInfo;
     457               0 :     psData = CPLParseXMLFile( osFilename );
     458               0 :     if (psData == NULL)
     459               0 :         return NULL;
     460                 : 
     461                 :     /* find the product components */
     462               0 :     psComponents = CPLGetXMLNode( psData, "=level1Product.productComponents" );
     463               0 :     if (psComponents == NULL) {
     464                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     465               0 :             "Unable to find <productComponents> tag in file.\n" );
     466               0 :         CPLDestroyXMLNode(psData);
     467               0 :         return NULL;
     468                 :     }
     469                 : 
     470                 :     /* find the product info tag */
     471               0 :     psProductInfo = CPLGetXMLNode( psData, "=level1Product.productInfo" );
     472               0 :     if (psProductInfo == NULL) {
     473                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     474               0 :             "Unable to find <productInfo> tag in file.\n" );
     475               0 :         CPLDestroyXMLNode(psData);
     476               0 :         return NULL;
     477                 :     }
     478                 : 
     479                 : /* -------------------------------------------------------------------- */
     480                 : /*      Create the dataset.                                             */
     481                 : /* -------------------------------------------------------------------- */
     482                 : 
     483               0 :     TSXDataset *poDS = new TSXDataset();
     484                 : 
     485                 : /* -------------------------------------------------------------------- */
     486                 : /*      Read in product info.                                           */
     487                 : /* -------------------------------------------------------------------- */
     488                 : 
     489                 :     poDS->SetMetadataItem( "SCENE_CENTRE_TIME", CPLGetXMLValue( psProductInfo,
     490               0 :         "sceneInfo.sceneCenterCoord.azimuthTimeUTC", "unknown" ) );
     491                 :     poDS->SetMetadataItem( "OPERATIONAL_MODE", CPLGetXMLValue( psProductInfo,
     492               0 :         "generationInfo.groundOperationsType", "unknown" ) );
     493                 :     poDS->SetMetadataItem( "ORBIT_CYCLE", CPLGetXMLValue( psProductInfo,
     494               0 :         "missionInfo.orbitCycle", "unknown" ) );
     495                 :     poDS->SetMetadataItem( "ABSOLUTE_ORBIT", CPLGetXMLValue( psProductInfo,
     496               0 :         "missionInfo.absOrbit", "unknown" ) );
     497                 :     poDS->SetMetadataItem( "ORBIT_DIRECTION", CPLGetXMLValue( psProductInfo,
     498               0 :         "missionInfo.orbitDirection", "unknown" ) );
     499                 :     poDS->SetMetadataItem( "IMAGING_MODE", CPLGetXMLValue( psProductInfo,
     500               0 :         "acquisitionInfo.imagingMode", "unknown" ) );
     501                 :     poDS->SetMetadataItem( "PRODUCT_VARIANT", CPLGetXMLValue( psProductInfo,
     502               0 :         "productVariantInfo.productVariant", "unknown" ) );
     503                 :     char *pszDataType = CPLStrdup( CPLGetXMLValue( psProductInfo,
     504               0 :         "imageDataInfo.imageDataType", "unknown" ) );
     505               0 :     poDS->SetMetadataItem( "IMAGE_TYPE", pszDataType );
     506                 : 
     507                 :     /* Get raster information */
     508                 :     int nRows = atoi( CPLGetXMLValue( psProductInfo,
     509               0 :         "imageDataInfo.imageRaster.numberOfRows", "" ) );
     510                 :     int nCols = atoi( CPLGetXMLValue( psProductInfo,
     511               0 :         "imageDataInfo.imageRaster.numberOfColumns", "" ) );
     512                 : 
     513               0 :     poDS->nRasterXSize = nCols;
     514               0 :     poDS->nRasterYSize = nRows;
     515                 : 
     516                 :     poDS->SetMetadataItem( "ROW_SPACING", CPLGetXMLValue( psProductInfo,
     517               0 :         "imageDataInfo.imageRaster.rowSpacing", "unknown" ) );
     518                 :     poDS->SetMetadataItem( "COL_SPACING", CPLGetXMLValue( psProductInfo,
     519               0 :         "imageDataInfo.imageRaster.columnSpacing", "unknown" ) );
     520                 :     poDS->SetMetadataItem( "COL_SPACING_UNITS", CPLGetXMLValue( psProductInfo,
     521               0 :         "imageDataInfo.imageRaster.columnSpacing.units", "unknown" ) );
     522                 : 
     523                 :     /* Get equivalent number of looks */
     524                 :     poDS->SetMetadataItem( "AZIMUTH_LOOKS", CPLGetXMLValue( psProductInfo,
     525               0 :         "imageDataInfo.imageRaster.azimuthLooks", "unknown" ) );
     526                 :     poDS->SetMetadataItem( "RANGE_LOOKS", CPLGetXMLValue( psProductInfo,
     527               0 :         "imageDataInfo.imageRaster.rangeLooks", "unknown" ) );
     528                 : 
     529                 :     const char *pszProductVariant;
     530                 :     pszProductVariant = CPLGetXMLValue( psProductInfo,
     531               0 :         "productVariantInfo.productVariant", "unknown" );
     532                 : 
     533               0 :     poDS->SetMetadataItem( "PRODUCT_VARIANT", pszProductVariant );
     534                 : 
     535                 :     /* Determine what product variant this is */
     536               0 :     if (EQUALN(pszProductVariant,"SSC",3))
     537               0 :         poDS->nProduct = eSSC;
     538               0 :     else if (EQUALN(pszProductVariant,"MGD",3))
     539               0 :         poDS->nProduct = eMGD;
     540               0 :     else if (EQUALN(pszProductVariant,"EEC",3))
     541               0 :         poDS->nProduct = eEEC;
     542               0 :     else if (EQUALN(pszProductVariant,"GEC",3))
     543               0 :         poDS->nProduct = eGEC;
     544                 :     else
     545               0 :         poDS->nProduct = eUnknown;
     546                 : 
     547                 :     /* Start reading in the product components */
     548                 :     const char *pszPath;
     549               0 :     char *pszGeorefFile = NULL;
     550                 :     CPLXMLNode *psComponent;
     551               0 :     CPLErr geoTransformErr=CE_Failure;
     552               0 :     for (psComponent = psComponents->psChild; psComponent != NULL;
     553                 :          psComponent = psComponent->psNext)
     554                 :     {
     555               0 :         const char *pszType = NULL;
     556                 :         pszPath = CPLFormFilename(
     557                 :                 CPLGetDirname( osFilename ),
     558                 :                 GetFilePath(psComponent, &pszType),
     559               0 :                 "" );
     560               0 :         const char *pszPolLayer = CPLGetXMLValue(psComponent, "polLayer", " ");
     561                 : 
     562               0 :         if ( !EQUALN(pszType," ",1) ) {
     563               0 :             if (EQUALN(pszType, "MAPPING_GRID", 12) ) {
     564                 :                 /* the mapping grid... save as a metadata item this path */
     565               0 :                 poDS->SetMetadataItem( "MAPPING_GRID", pszPath );
     566                 :             }
     567               0 :             else if (EQUALN(pszType, "GEOREF", 6)) {
     568                 :                 /* save the path to the georef data for later use */
     569               0 :                 pszGeorefFile = CPLStrdup( pszPath );
     570                 :             }
     571                 :         }
     572               0 :         else if( !EQUALN(pszPolLayer, " ", 1) &&
     573                 :             EQUALN(psComponent->pszValue, "imageData", 9) ) {
     574                 :             /* determine the polarization of this band */
     575                 :             ePolarization ePol;
     576               0 :             if ( EQUALN(pszPolLayer, "HH", 2) ) {
     577               0 :                 ePol = HH;
     578                 :             }
     579               0 :             else if ( EQUALN(pszPolLayer, "HV" , 2) ) {
     580               0 :                 ePol = HV;
     581                 :             }
     582               0 :             else if ( EQUALN(pszPolLayer, "VH", 2) ) {
     583               0 :                 ePol = VH;
     584                 :             }
     585                 :             else {
     586               0 :                 ePol = VV;
     587                 :             }
     588                 : 
     589                 :             GDALDataType eDataType = EQUALN(pszDataType, "COMPLEX", 7) ?
     590               0 :                 GDT_CInt16 : GDT_UInt16;
     591                 : 
     592                 :             /* try opening the file that represents that band */
     593                 :             TSXRasterBand *poBand;
     594                 :             GDALDataset *poBandData;
     595                 : 
     596               0 :             poBandData = (GDALDataset *) GDALOpen( pszPath, GA_ReadOnly );
     597               0 :             if ( poBandData != NULL ) {
     598                 :                 poBand = new TSXRasterBand( poDS, eDataType, ePol,
     599               0 :                     poBandData );
     600               0 :                 poDS->SetBand( poDS->GetRasterCount() + 1, poBand );
     601                 : 
     602                 :                 //copy georeferencing info from the band
     603                 :                 //need error checking??
     604                 :                 //it will just save the info from the last band
     605               0 :                 CPLFree( poDS->pszProjection );
     606               0 :                 poDS->pszProjection = CPLStrdup(poBandData->GetProjectionRef());
     607               0 :                 geoTransformErr = poBandData->GetGeoTransform(poDS->adfGeoTransform);
     608                 :             }
     609                 :         }
     610                 :     }
     611                 : 
     612                 :     //now check if there is a geotransform
     613               0 :     if ( strcmp(poDS->pszProjection, "") && geoTransformErr==CE_None)
     614                 :     {
     615               0 :         poDS->bHaveGeoTransform = TRUE;
     616                 :     }
     617                 :     else
     618                 :     {
     619               0 :         poDS->bHaveGeoTransform = FALSE;
     620               0 :         CPLFree( poDS->pszProjection );
     621               0 :         poDS->pszProjection = CPLStrdup("");
     622               0 :         poDS->adfGeoTransform[0] = 0.0;
     623               0 :         poDS->adfGeoTransform[1] = 1.0;
     624               0 :         poDS->adfGeoTransform[2] = 0.0;
     625               0 :         poDS->adfGeoTransform[3] = 0.0;
     626               0 :         poDS->adfGeoTransform[4] = 0.0;
     627               0 :         poDS->adfGeoTransform[5] = 1.0;
     628                 :     }
     629                 : 
     630               0 :     CPLFree(pszDataType);
     631                 : 
     632                 : 
     633                 : /* -------------------------------------------------------------------- */
     634                 : /*      Check and set matrix representation.                            */
     635                 : /* -------------------------------------------------------------------- */
     636                 : 
     637               0 :     if (poDS->GetRasterCount() == 4) {
     638               0 :         poDS->SetMetadataItem( "MATRIX_REPRESENTATION", "SCATTERING" );
     639                 :     }
     640                 : 
     641                 : /* -------------------------------------------------------------------- */
     642                 : /*      Read the four corners and centre GCPs in                        */
     643                 : /* -------------------------------------------------------------------- */
     644                 : 
     645                 :     CPLXMLNode *psSceneInfo = CPLGetXMLNode( psData,
     646               0 :         "=level1Product.productInfo.sceneInfo" );
     647               0 :     if (psSceneInfo != NULL)
     648                 :     {
     649                 :         /* extract the GCPs from the provided file */
     650               0 :         bool success = false;
     651               0 :         if (pszGeorefFile != NULL)
     652               0 :             success = poDS->getGCPsFromGEOREF_XML(pszGeorefFile);
     653                 : 
     654                 :         //if the gcp's cannot be extracted from the georef file, try to get the corner coordinates
     655                 :         //for now just SSC because the others don't have refColumn and refRow
     656               0 :         if (!success && poDS->nProduct == eSSC)
     657                 :         {
     658                 :             CPLXMLNode *psNode;
     659               0 :             int nGCP = 0;
     660                 :             double dfAvgHeight = atof(CPLGetXMLValue(psSceneInfo,
     661               0 :                 "sceneAverageHeight", "0.0"));
     662                 : 
     663                 :             //count and allocate gcps - there should be five - 4 corners and a centre
     664               0 :             poDS->nGCPCount = 0;
     665               0 :             for (psNode = psSceneInfo->psChild; psNode != NULL; psNode = psNode->psNext )
     666                 :             {
     667               0 :                 if (!EQUAL(psNode->pszValue, "sceneCenterCoord") &&
     668                 :                     !EQUAL(psNode->pszValue, "sceneCornerCoord"))
     669               0 :                     continue;
     670                 : 
     671               0 :                 poDS->nGCPCount++;
     672                 :             }
     673               0 :             if (poDS->nGCPCount > 0)
     674                 :             {
     675               0 :                 poDS->pasGCPList = (GDAL_GCP *)CPLCalloc(sizeof(GDAL_GCP), poDS->nGCPCount);
     676                 : 
     677                 :                 /* iterate over GCPs */
     678               0 :                 for (psNode = psSceneInfo->psChild; psNode != NULL; psNode = psNode->psNext )
     679                 :                 {
     680               0 :                     GDAL_GCP *psGCP = poDS->pasGCPList + nGCP;
     681                 : 
     682               0 :                     if (!EQUAL(psNode->pszValue, "sceneCenterCoord") &&
     683                 :                         !EQUAL(psNode->pszValue, "sceneCornerCoord"))
     684               0 :                         continue;
     685                 : 
     686                 :                     psGCP->dfGCPPixel = atof(CPLGetXMLValue(psNode, "refColumn",
     687               0 :                         "0.0"));
     688               0 :                     psGCP->dfGCPLine = atof(CPLGetXMLValue(psNode, "refRow", "0.0"));
     689               0 :                     psGCP->dfGCPX = atof(CPLGetXMLValue(psNode, "lon", "0.0"));
     690               0 :                     psGCP->dfGCPY = atof(CPLGetXMLValue(psNode, "lat", "0.0"));
     691               0 :                     psGCP->dfGCPZ = dfAvgHeight;
     692               0 :                     psGCP->pszId = CPLStrdup( CPLSPrintf( "%d", nGCP ) );
     693               0 :                     psGCP->pszInfo = CPLStrdup("");
     694                 : 
     695               0 :                     nGCP++;
     696                 :                 }
     697                 : 
     698                 :                 //set the projection string - the fields are lat/long - seems to be WGS84 datum
     699               0 :                 OGRSpatialReference osr;
     700               0 :                 osr.SetWellKnownGeogCS( "WGS84" );
     701               0 :                 CPLFree(poDS->pszGCPProjection);
     702               0 :                 osr.exportToWkt( &(poDS->pszGCPProjection) );
     703                 :             }
     704                 :         }
     705                 : 
     706                 :         //gcps override geotransform - does it make sense to have both??
     707               0 :         if (poDS->nGCPCount>0)
     708                 :         {
     709               0 :             poDS->bHaveGeoTransform = FALSE;
     710               0 :             CPLFree( poDS->pszProjection );
     711               0 :             poDS->pszProjection = CPLStrdup("");
     712               0 :             poDS->adfGeoTransform[0] = 0.0;
     713               0 :             poDS->adfGeoTransform[1] = 1.0;
     714               0 :             poDS->adfGeoTransform[2] = 0.0;
     715               0 :             poDS->adfGeoTransform[3] = 0.0;
     716               0 :             poDS->adfGeoTransform[4] = 0.0;
     717               0 :             poDS->adfGeoTransform[5] = 1.0;
     718                 :         }
     719                 : 
     720                 :     }
     721                 :     else {
     722                 :         CPLError(CE_Warning, CPLE_AppDefined,
     723                 :             "Unable to find sceneInfo tag in XML document. "
     724               0 :             "Proceeding with caution.");
     725                 :     }
     726                 : 
     727               0 :     CPLFree(pszGeorefFile);
     728                 : 
     729                 : /* -------------------------------------------------------------------- */
     730                 : /*      Initialize any PAM information.                                 */
     731                 : /* -------------------------------------------------------------------- */
     732               0 :     poDS->SetDescription( poOpenInfo->pszFilename );
     733               0 :     poDS->TryLoadXML();
     734                 : 
     735                 : /* -------------------------------------------------------------------- */
     736                 : /*      Check for overviews.                                            */
     737                 : /* -------------------------------------------------------------------- */
     738               0 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     739                 : 
     740               0 :     CPLDestroyXMLNode(psData);
     741                 : 
     742               0 :     return poDS;
     743                 : }
     744                 : 
     745                 : /************************************************************************/
     746                 : /*                            GetGCPCount()                             */
     747                 : /************************************************************************/
     748                 : 
     749               0 : int TSXDataset::GetGCPCount() {
     750               0 :     return nGCPCount;
     751                 : }
     752                 : 
     753                 : /************************************************************************/
     754                 : /*                          GetGCPProjection()                          */
     755                 : /************************************************************************/
     756                 : 
     757               0 : const char *TSXDataset::GetGCPProjection() {
     758               0 :     return pszGCPProjection;
     759                 : }
     760                 : 
     761                 : /************************************************************************/
     762                 : /*                               GetGCPs()                              */
     763                 : /************************************************************************/
     764                 : 
     765               0 : const GDAL_GCP *TSXDataset::GetGCPs() {
     766               0 :     return pasGCPList;
     767                 : }
     768                 : 
     769                 : /************************************************************************/
     770                 : /*                          GetProjectionRef()                          */
     771                 : /************************************************************************/
     772               0 : const char *TSXDataset::GetProjectionRef()
     773                 : {
     774               0 :     return pszProjection;
     775                 : }
     776                 : 
     777                 : /************************************************************************/
     778                 : /*                               GetGeotransform()                      */
     779                 : /************************************************************************/
     780               0 : CPLErr TSXDataset::GetGeoTransform(double* padfTransform)
     781                 : {
     782               0 :     memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
     783                 : 
     784               0 :     if (bHaveGeoTransform)
     785               0 :         return( CE_None );
     786                 : 
     787               0 :     return( CE_Failure );
     788                 : }
     789                 : 
     790                 : /************************************************************************/
     791                 : /*                         GDALRegister_TSX()                           */
     792                 : /************************************************************************/
     793                 : 
     794             582 : void GDALRegister_TSX() {
     795                 :     GDALDriver    *poDriver;
     796                 : 
     797             582 :     if( GDALGetDriverByName( "TSX" ) == NULL )
     798                 :     {
     799             561 :         poDriver = new GDALDriver();
     800                 : 
     801             561 :         poDriver->SetDescription( "TSX" );
     802                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
     803             561 :                                    "TerraSAR-X Product" );
     804                 : /*        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_tsx.html" ); */
     805                 : 
     806             561 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
     807                 : 
     808             561 :         poDriver->pfnOpen = TSXDataset::Open;
     809             561 :         poDriver->pfnIdentify = TSXDataset::Identify;
     810                 : 
     811             561 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     812                 :     }
     813             582 : }
     814                 : 

Generated by: LCOV version 1.7