LCOV - code coverage report
Current view: directory - frmts/map - mapdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 188 136 72.3 %
Date: 2013-03-30 Functions: 19 11 57.9 %

       1                 : /******************************************************************************
       2                 :  *
       3                 :  * Project:  OziExplorer .MAP Driver
       4                 :  * Purpose:  GDALDataset driver for OziExplorer .MAP files
       5                 :  * Author:   Jean-Claude Repetto, <jrepetto at @free dot fr>
       6                 :  *
       7                 :  ******************************************************************************
       8                 :  * Copyright (c) 2012, Jean-Claude Repetto
       9                 :  *
      10                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      11                 :  * copy of this software and associated documentation files (the "Software"),
      12                 :  * to deal in the Software without restriction, including without limitation
      13                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14                 :  * and/or sell copies of the Software, and to permit persons to whom the
      15                 :  * Software is furnished to do so, subject to the following conditions:
      16                 :  *
      17                 :  * The above copyright notice and this permission notice shall be included
      18                 :  * in all copies or substantial portions of the Software.
      19                 :  *
      20                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26                 :  * DEALINGS IN THE SOFTWARE.
      27                 :  ****************************************************************************/
      28                 : 
      29                 : #include "gdal_pam.h"
      30                 : #include "gdal_proxy.h"
      31                 : #include "ogr_spatialref.h"
      32                 : #include "ogr_geometry.h"
      33                 : 
      34                 : CPL_CVSID("$Id: mapdataset.cpp 25369 2012-12-27 19:06:27Z rouault $");
      35                 : 
      36                 : /************************************************************************/
      37                 : /* ==================================================================== */
      38                 : /*                                MAPDataset                            */
      39                 : /* ==================================================================== */
      40                 : /************************************************************************/
      41                 : 
      42                 : class CPL_DLL MAPDataset : public GDALDataset
      43                 : {
      44                 :     GDALDataset *poImageDS;
      45                 : 
      46                 :     char        *pszWKT;
      47                 :     int         bGeoTransformValid;
      48                 :     double      adfGeoTransform[6];
      49                 :     int         nGCPCount;
      50                 :     GDAL_GCP  *pasGCPList;
      51                 :     OGRPolygon  *poNeatLine;
      52                 :     CPLString   osImgFilename;
      53                 : 
      54                 :   public:
      55                 :     MAPDataset();
      56                 :     virtual ~MAPDataset();
      57                 : 
      58                 :     virtual const char* GetProjectionRef();
      59                 :     virtual CPLErr      GetGeoTransform( double * );
      60                 :     virtual int GetGCPCount();
      61                 :     virtual const char *GetGCPProjection();
      62                 :     virtual const GDAL_GCP *GetGCPs();
      63                 :     virtual char **GetFileList();
      64                 : 
      65                 :     virtual int         CloseDependentDatasets();
      66                 : 
      67                 :     static GDALDataset *Open( GDALOpenInfo * );
      68                 :     static int Identify( GDALOpenInfo *poOpenInfo );
      69                 : };
      70                 : 
      71                 : /************************************************************************/
      72                 : /* ==================================================================== */
      73                 : /*                         MAPWrapperRasterBand                         */
      74                 : /* ==================================================================== */
      75                 : /************************************************************************/
      76                 : class MAPWrapperRasterBand : public GDALProxyRasterBand
      77                 : {
      78                 :   GDALRasterBand* poBaseBand;
      79                 : 
      80                 :   protected:
      81            1480 :     virtual GDALRasterBand* RefUnderlyingRasterBand() { return poBaseBand; }
      82                 : 
      83                 :   public:
      84               1 :     MAPWrapperRasterBand( GDALRasterBand* poBaseBand )
      85               1 :         {
      86               1 :             this->poBaseBand = poBaseBand;
      87               1 :             eDataType = poBaseBand->GetRasterDataType();
      88               1 :             poBaseBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
      89               1 :         }
      90               1 :     ~MAPWrapperRasterBand() {}
      91                 : };
      92                 : 
      93                 : /************************************************************************/
      94                 : /* ==================================================================== */
      95                 : /*                             MAPDataset                               */
      96                 : /* ==================================================================== */
      97                 : /************************************************************************/
      98                 : 
      99               1 : MAPDataset::MAPDataset()
     100                 : 
     101                 : {
     102               1 :     poImageDS = NULL;
     103               1 :     pszWKT = NULL;
     104               1 :     adfGeoTransform[0] = 0.0;
     105               1 :     adfGeoTransform[1] = 1.0;
     106               1 :     adfGeoTransform[2] = 0.0;
     107               1 :     adfGeoTransform[3] = 0.0;
     108               1 :     adfGeoTransform[4] = 0.0;
     109               1 :     adfGeoTransform[5] = 1.0;
     110               1 :     nGCPCount = 0;
     111               1 :     pasGCPList = NULL;
     112               1 :     poNeatLine = NULL;
     113               1 :     bGeoTransformValid = false;
     114               1 : }
     115                 : 
     116                 : /************************************************************************/
     117                 : /*                            ~MAPDataset()                             */
     118                 : /************************************************************************/
     119                 : 
     120               1 : MAPDataset::~MAPDataset()
     121                 : 
     122                 : {
     123               1 :     if (poImageDS != NULL)
     124                 :     {
     125               1 :         GDALClose( poImageDS );
     126               1 :         poImageDS = NULL;
     127                 :     }
     128               1 :     if (pszWKT != NULL)
     129                 :     {
     130               1 :         CPLFree(pszWKT);
     131               1 :         pszWKT = NULL;
     132                 :     }
     133               1 :     if (nGCPCount)
     134                 :     {
     135               1 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     136               1 :         CPLFree(pasGCPList);
     137                 :     }
     138                 : 
     139               1 :     if ( poNeatLine != NULL )
     140                 :     {
     141               1 :         delete poNeatLine;
     142               1 :         poNeatLine = NULL;
     143                 :     }
     144               1 : }
     145                 : 
     146                 : /************************************************************************/
     147                 : /*                       CloseDependentDatasets()                       */
     148                 : /************************************************************************/
     149                 : 
     150               0 : int MAPDataset::CloseDependentDatasets()
     151                 : {
     152               0 :     int bRet = GDALDataset::CloseDependentDatasets();
     153               0 :     if (poImageDS != NULL)
     154                 :     {
     155               0 :         GDALClose( poImageDS );
     156               0 :         poImageDS = NULL;
     157               0 :         bRet = TRUE;
     158                 :     }
     159               0 :     return bRet;
     160                 : }
     161                 : 
     162                 : /************************************************************************/
     163                 : /*                              Identify()                              */
     164                 : /************************************************************************/
     165                 : 
     166           12436 : int MAPDataset::Identify( GDALOpenInfo *poOpenInfo )
     167                 : 
     168                 : {
     169           12436 :     if( poOpenInfo->nHeaderBytes < 200 
     170                 :         || !EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"MAP") )
     171           12435 :         return FALSE;
     172                 : 
     173               1 :     if( strstr((const char *) poOpenInfo->pabyHeader,"OziExplorer Map Data File") == NULL )
     174               0 :         return FALSE;
     175                 :     else
     176               1 :         return TRUE;
     177                 : }
     178                 : 
     179                 : /************************************************************************/
     180                 : /*                                Open()                                */
     181                 : /************************************************************************/
     182                 : 
     183                 : #define MAX_GCP 30
     184                 : 
     185            2305 : GDALDataset *MAPDataset::Open( GDALOpenInfo * poOpenInfo )
     186                 : {
     187            2305 :     if( !Identify( poOpenInfo ) )
     188            2304 :         return NULL;
     189                 : 
     190                 : /* -------------------------------------------------------------------- */
     191                 : /*      Confirm the requested access is supported.                      */
     192                 : /* -------------------------------------------------------------------- */
     193               1 :     if( poOpenInfo->eAccess == GA_Update )
     194                 :     {
     195                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     196                 :                   "The MAP driver does not support update access to existing"
     197               0 :                   " datasets.\n" );
     198               0 :         return NULL;
     199                 :     }
     200                 :     
     201                 : /* -------------------------------------------------------------------- */
     202                 : /*      Create a corresponding GDALDataset.                             */
     203                 : /* -------------------------------------------------------------------- */
     204                 : 
     205               1 :     MAPDataset *poDS = new MAPDataset();
     206                 : 
     207                 : /* -------------------------------------------------------------------- */
     208                 : /*      Try to load and parse the .MAP file.                            */
     209                 : /* -------------------------------------------------------------------- */
     210                 : 
     211                 :     int bOziFileOK = 
     212                 :          GDALLoadOziMapFile( poOpenInfo->pszFilename,
     213                 :                              poDS->adfGeoTransform, 
     214                 :                              &poDS->pszWKT,
     215               1 :                              &poDS->nGCPCount, &poDS->pasGCPList );
     216                 : 
     217               2 :     if ( bOziFileOK && poDS->nGCPCount == 0 )
     218               0 :          poDS->bGeoTransformValid = TRUE;
     219                 : 
     220                 :    /* We need to read again the .map file because the GDALLoadOziMapFile function
     221                 :       does not returns all required data . An API change is necessary : maybe in GDAL 2.0 ? */
     222                 : 
     223                 :     char  **papszLines;
     224               1 :     int   iLine, nLines=0;
     225                 : 
     226               1 :     papszLines = CSLLoad2( poOpenInfo->pszFilename, 200, 200, NULL );
     227                 : 
     228               1 :     if ( !papszLines )
     229               0 :         return NULL;
     230                 : 
     231               1 :     nLines = CSLCount( papszLines );
     232               1 :     if( nLines < 2 )
     233                 :     {
     234               0 :         CSLDestroy(papszLines);
     235               0 :         return NULL;
     236                 :     }
     237                 : 
     238                 : /* -------------------------------------------------------------------- */
     239                 : /*      We need to open the image in order to establish                 */
     240                 : /*      details like the band count and types.                          */
     241                 : /* -------------------------------------------------------------------- */
     242               1 :     poDS->osImgFilename = papszLines[2];
     243                 :     VSIStatBufL sStat;
     244               1 :     if (VSIStatL(poDS->osImgFilename, &sStat) != 0)
     245                 :     {
     246               1 :         CPLString osPath = CPLGetPath(poOpenInfo->pszFilename);
     247               1 :         if (CPLIsFilenameRelative(poDS->osImgFilename))
     248                 :         {
     249               1 :             poDS->osImgFilename = CPLFormFilename(osPath, poDS->osImgFilename, NULL);
     250                 :         }
     251                 :         else
     252                 :         {
     253               0 :             poDS->osImgFilename = CPLGetFilename(poDS->osImgFilename);
     254               0 :             poDS->osImgFilename = CPLFormFilename(osPath, poDS->osImgFilename, NULL);
     255               1 :         }
     256                 :     }
     257                 : 
     258                 : /* -------------------------------------------------------------------- */
     259                 : /*      Try and open the file.                                          */
     260                 : /* -------------------------------------------------------------------- */
     261               1 :     poDS->poImageDS = (GDALDataset *) GDALOpen(poDS->osImgFilename, GA_ReadOnly );
     262               1 :     if( poDS->poImageDS == NULL || poDS->poImageDS->GetRasterCount() == 0)
     263                 :     {
     264               0 :         CSLDestroy(papszLines);
     265               0 :         delete poDS;
     266               0 :         return NULL;
     267                 :     }
     268                 : 
     269                 : /* -------------------------------------------------------------------- */
     270                 : /*      Attach the bands.                                               */
     271                 : /* -------------------------------------------------------------------- */
     272                 :     int iBand;
     273                 : 
     274               1 :     poDS->nRasterXSize = poDS->poImageDS->GetRasterXSize();
     275               1 :     poDS->nRasterYSize = poDS->poImageDS->GetRasterYSize();
     276               1 :     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
     277                 :     {
     278               0 :         delete poDS;
     279               0 :         GDALClose( poDS->poImageDS );
     280               0 :         return NULL;
     281                 :     }
     282                 : 
     283               4 :     for( iBand = 1; iBand <= poDS->poImageDS->GetRasterCount(); iBand++ )
     284                 :         poDS->SetBand( iBand,
     285               1 :                        new MAPWrapperRasterBand( poDS->poImageDS->GetRasterBand( iBand )) );
     286                 : 
     287                 : /* -------------------------------------------------------------------- */
     288                 : /*      Add the neatline/cutline, if required                           */
     289                 : /* -------------------------------------------------------------------- */
     290                 : 
     291                 :     /* First, we need to check if it is necessary to define a neatline */
     292               1 :     bool bNeatLine = false;
     293                 :     char **papszTok;
     294              36 :     for ( iLine = 10; iLine < nLines; iLine++ )
     295                 :     {
     296              36 :         if ( EQUALN(papszLines[iLine], "MMPXY,", 6) )
     297                 :         {
     298               1 :             papszTok = CSLTokenizeString2( papszLines[iLine], ",",
     299                 :                                            CSLT_STRIPLEADSPACES
     300               2 :                                            | CSLT_STRIPENDSPACES );
     301                 : 
     302               1 :             if ( CSLCount(papszTok) != 4 )
     303                 :             {
     304               0 :                 CSLDestroy(papszTok);
     305               0 :                 continue;
     306                 :             }
     307                 : 
     308               1 :             int x = CPLAtofM(papszTok[2]);
     309               1 :             int y = CPLAtofM(papszTok[3]);
     310               1 :             if (( x != 0 && x != poDS->nRasterXSize) || (y != 0 && y != poDS->nRasterYSize) )
     311                 :             {
     312               1 :                 bNeatLine = true;
     313               1 :                 CSLDestroy(papszTok);
     314               1 :                 break;
     315                 :             }
     316               0 :             CSLDestroy(papszTok);
     317                 :         }
     318                 :     }
     319                 : 
     320                 :     /* Create and fill the neatline polygon */
     321               1 :     if (bNeatLine)
     322                 :     {
     323               1 :         poDS->poNeatLine = new OGRPolygon(); /* Create a polygon to store the neatline */
     324               2 :         OGRLinearRing* poRing = new OGRLinearRing();
     325                 : 
     326               1 :         if ( poDS->bGeoTransformValid )        /* Compute the projected coordinates of the corners */
     327                 :         {
     328               0 :             for ( iLine = 10; iLine < nLines; iLine++ )
     329                 :             {
     330               0 :                 if ( EQUALN(papszLines[iLine], "MMPXY,", 6) )
     331                 :                 {
     332               0 :                     papszTok = CSLTokenizeString2( papszLines[iLine], ",",
     333                 :                                                    CSLT_STRIPLEADSPACES
     334               0 :                                                    | CSLT_STRIPENDSPACES );
     335                 : 
     336               0 :                     if ( CSLCount(papszTok) != 4 )
     337                 :                     {
     338               0 :                         CSLDestroy(papszTok);
     339               0 :                         continue;
     340                 :                     }
     341                 : 
     342               0 :                     double x = CPLAtofM(papszTok[2]);
     343               0 :                     double y = CPLAtofM(papszTok[3]);
     344               0 :                     double X = poDS->adfGeoTransform[0] + x * poDS->adfGeoTransform[1] +
     345               0 :                                             y * poDS->adfGeoTransform[2];
     346               0 :                     double Y = poDS->adfGeoTransform[3] + x * poDS->adfGeoTransform[4] +
     347               0 :                                             y * poDS->adfGeoTransform[5];
     348               0 :                     poRing->addPoint(X, Y);
     349               0 :                     CPLDebug( "CORNER MMPXY", "%f, %f, %f, %f", x, y, X, Y);
     350               0 :                     CSLDestroy(papszTok);
     351                 :                 }
     352                 :             }
     353                 :         }
     354                 :         else /* Convert the geographic coordinates to projected coordinates */
     355                 :         {
     356               1 :             OGRSpatialReference oSRS;
     357               1 :             OGRSpatialReference *poLatLong = NULL;
     358               1 :             OGRCoordinateTransformation *poTransform = NULL;
     359                 :             OGRErr eErr;
     360               1 :             char *pszWKT = poDS->pszWKT;
     361                 : 
     362               1 :             if ( &poDS->pszWKT != NULL )
     363                 :             {
     364               1 :                 eErr = oSRS.importFromWkt ( &pszWKT );
     365               1 :                 if ( eErr == OGRERR_NONE )
     366               1 :                     poLatLong = oSRS.CloneGeogCS();
     367               1 :                     if ( poLatLong )
     368               1 :                         poTransform = OGRCreateCoordinateTransformation( poLatLong, &oSRS );
     369                 :             }
     370                 : 
     371              47 :             for ( iLine = 10; iLine < nLines; iLine++ )
     372                 :             {
     373              46 :                 if ( EQUALN(papszLines[iLine], "MMPLL,", 6) )
     374                 :                 {
     375               4 :                     CPLDebug( "MMPLL", "%s", papszLines[iLine] );
     376               4 :                     char **papszTok = NULL;
     377                 : 
     378               4 :                     papszTok = CSLTokenizeString2( papszLines[iLine], ",",
     379                 :                                                    CSLT_STRIPLEADSPACES
     380               8 :                                                    | CSLT_STRIPENDSPACES );
     381                 : 
     382               4 :                     if ( CSLCount(papszTok) != 4 )
     383                 :                     {
     384               0 :                          CSLDestroy(papszTok);
     385               0 :                          continue;
     386                 :                     }
     387                 : 
     388               4 :                     double dfLon = CPLAtofM(papszTok[2]);
     389               4 :                     double dfLat = CPLAtofM(papszTok[3]);
     390                 : 
     391               4 :                     if ( poTransform )
     392               4 :                         poTransform->Transform( 1, &dfLon, &dfLat );
     393               4 :                     poRing->addPoint(dfLon, dfLat);
     394               4 :                     CPLDebug( "CORNER MMPLL", "%f, %f", dfLon, dfLat);
     395               4 :                     CSLDestroy(papszTok);
     396                 :                 }
     397                 :             }
     398               1 :             if (poTransform)
     399               1 :                 delete poTransform;
     400               1 :             if (poLatLong)
     401               1 :                 delete poLatLong;
     402                 :         }
     403                 : 
     404               1 :         poRing->closeRings();
     405               1 :         poDS->poNeatLine->addRingDirectly(poRing);
     406                 : 
     407               1 :         char* pszNeatLineWkt = NULL;
     408               1 :         poDS->poNeatLine->exportToWkt(&pszNeatLineWkt);
     409               1 :         CPLDebug( "NEATLINE", "%s", pszNeatLineWkt);
     410               1 :         poDS->SetMetadataItem("NEATLINE", pszNeatLineWkt);
     411               1 :         CPLFree(pszNeatLineWkt);
     412                 :     }
     413                 : 
     414               1 :     CSLDestroy(papszLines);
     415                 : 
     416               1 :     return( poDS );
     417                 : }
     418                 : 
     419                 : /************************************************************************/
     420                 : /*                          GetProjectionRef()                          */
     421                 : /************************************************************************/
     422                 : 
     423               0 : const char* MAPDataset::GetProjectionRef()
     424                 : {
     425               0 :     return (pszWKT && nGCPCount == 0) ? pszWKT : "";
     426                 : }
     427                 : 
     428                 : /************************************************************************/
     429                 : /*                          GetGeoTransform()                           */
     430                 : /************************************************************************/
     431                 : 
     432               0 : CPLErr MAPDataset::GetGeoTransform( double * padfTransform )
     433                 : 
     434                 : {
     435               0 :     memcpy(padfTransform, adfGeoTransform, 6 * sizeof(double));
     436                 : 
     437               0 :     return( (nGCPCount == 0) ? CE_None : CE_Failure );
     438                 : }
     439                 : 
     440                 : 
     441                 : /************************************************************************/
     442                 : /*                           GetGCPCount()                              */
     443                 : /************************************************************************/
     444                 : 
     445               1 : int MAPDataset::GetGCPCount()
     446                 : {
     447               1 :     return nGCPCount;
     448                 : }
     449                 : 
     450                 : /************************************************************************/
     451                 : /*                          GetGCPProjection()                          */
     452                 : /************************************************************************/
     453                 : 
     454               1 : const char * MAPDataset::GetGCPProjection()
     455                 : {
     456               1 :     return (pszWKT && nGCPCount != 0) ? pszWKT : "";
     457                 : }
     458                 : 
     459                 : /************************************************************************/
     460                 : /*                               GetGCPs()                              */
     461                 : /************************************************************************/
     462                 : 
     463               1 : const GDAL_GCP * MAPDataset::GetGCPs()
     464                 : {
     465               1 :     return pasGCPList;
     466                 : }
     467                 : 
     468                 : /************************************************************************/
     469                 : /*                            GetFileList()                             */
     470                 : /************************************************************************/
     471                 : 
     472               0 : char** MAPDataset::GetFileList()
     473                 : {
     474               0 :     char **papszFileList = GDALDataset::GetFileList();
     475                 : 
     476               0 :     papszFileList = CSLAddString( papszFileList, osImgFilename );
     477                 :     
     478               0 :     return papszFileList;
     479                 : }
     480                 : 
     481                 : /************************************************************************/
     482                 : /*                          GDALRegister_MAP()                          */
     483                 : /************************************************************************/
     484                 : 
     485             610 : void GDALRegister_MAP()
     486                 : 
     487                 : {
     488                 :     GDALDriver  *poDriver;
     489                 : 
     490             610 :     if( GDALGetDriverByName( "MAP" ) == NULL )
     491                 :     {
     492             588 :         poDriver = new GDALDriver();
     493                 :         
     494             588 :         poDriver->SetDescription( "MAP" );
     495                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
     496             588 :                                    "OziExplorer .MAP" );
     497                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
     498             588 :                                    "frmt_map.html" );
     499                 : 
     500             588 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
     501                 : 
     502             588 :         poDriver->pfnOpen = MAPDataset::Open;
     503             588 :         poDriver->pfnIdentify = MAPDataset::Identify;
     504                 : 
     505             588 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     506                 :     }
     507             610 : }
     508                 : 
     509                 : 

Generated by: LCOV version 1.7