LCOV - code coverage report
Current view: directory - frmts/map - mapdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 181 136 75.1 %
Date: 2012-12-26 Functions: 18 11 61.1 %

       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 25287 2012-12-05 21:17:14Z 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                 :     static GDALDataset *Open( GDALOpenInfo * );
      66                 :     static int Identify( GDALOpenInfo *poOpenInfo );
      67                 : };
      68                 : 
      69                 : /************************************************************************/
      70                 : /* ==================================================================== */
      71                 : /*                         MAPWrapperRasterBand                         */
      72                 : /* ==================================================================== */
      73                 : /************************************************************************/
      74                 : class MAPWrapperRasterBand : public GDALProxyRasterBand
      75                 : {
      76                 :   GDALRasterBand* poBaseBand;
      77                 : 
      78                 :   protected:
      79            1480 :     virtual GDALRasterBand* RefUnderlyingRasterBand() { return poBaseBand; }
      80                 : 
      81                 :   public:
      82               1 :     MAPWrapperRasterBand( GDALRasterBand* poBaseBand )
      83               1 :         {
      84               1 :             this->poBaseBand = poBaseBand;
      85               1 :             eDataType = poBaseBand->GetRasterDataType();
      86               1 :             poBaseBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
      87               1 :         }
      88               1 :     ~MAPWrapperRasterBand() {}
      89                 : };
      90                 : 
      91                 : /************************************************************************/
      92                 : /* ==================================================================== */
      93                 : /*                             MAPDataset                               */
      94                 : /* ==================================================================== */
      95                 : /************************************************************************/
      96                 : 
      97               1 : MAPDataset::MAPDataset()
      98                 : 
      99                 : {
     100               1 :     poImageDS = NULL;
     101               1 :     pszWKT = NULL;
     102               1 :     adfGeoTransform[0] = 0.0;
     103               1 :     adfGeoTransform[1] = 1.0;
     104               1 :     adfGeoTransform[2] = 0.0;
     105               1 :     adfGeoTransform[3] = 0.0;
     106               1 :     adfGeoTransform[4] = 0.0;
     107               1 :     adfGeoTransform[5] = 1.0;
     108               1 :     nGCPCount = 0;
     109               1 :     pasGCPList = NULL;
     110               1 :     poNeatLine = NULL;
     111               1 :     bGeoTransformValid = false;
     112               1 : }
     113                 : 
     114                 : /************************************************************************/
     115                 : /*                            ~MAPDataset()                             */
     116                 : /************************************************************************/
     117                 : 
     118               1 : MAPDataset::~MAPDataset()
     119                 : 
     120                 : {
     121               1 :     if (poImageDS != NULL)
     122                 :     {
     123               1 :         GDALClose( poImageDS );
     124               1 :         poImageDS = NULL;
     125                 :     }
     126               1 :     if (pszWKT != NULL)
     127                 :     {
     128               1 :         CPLFree(pszWKT);
     129               1 :         pszWKT = NULL;
     130                 :     }
     131               1 :     if (nGCPCount)
     132                 :     {
     133               1 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     134               1 :         CPLFree(pasGCPList);
     135                 :     }
     136                 : 
     137               1 :     if ( poNeatLine != NULL )
     138                 :     {
     139               1 :         delete poNeatLine;
     140               1 :         poNeatLine = NULL;
     141                 :     }
     142               1 : }
     143                 : 
     144                 : /************************************************************************/
     145                 : /*                              Identify()                              */
     146                 : /************************************************************************/
     147                 : 
     148           12390 : int MAPDataset::Identify( GDALOpenInfo *poOpenInfo )
     149                 : 
     150                 : {
     151           12390 :     if( poOpenInfo->nHeaderBytes < 200 
     152                 :         || !EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"MAP") )
     153           12389 :         return FALSE;
     154                 : 
     155               1 :     if( strstr((const char *) poOpenInfo->pabyHeader,"OziExplorer Map Data File") == NULL )
     156               0 :         return FALSE;
     157                 :     else
     158               1 :         return TRUE;
     159                 : }
     160                 : 
     161                 : /************************************************************************/
     162                 : /*                                Open()                                */
     163                 : /************************************************************************/
     164                 : 
     165                 : #define MAX_GCP 30
     166                 : 
     167            2297 : GDALDataset *MAPDataset::Open( GDALOpenInfo * poOpenInfo )
     168                 : {
     169            2297 :     if( !Identify( poOpenInfo ) )
     170            2296 :         return NULL;
     171                 : 
     172                 : /* -------------------------------------------------------------------- */
     173                 : /*      Confirm the requested access is supported.                      */
     174                 : /* -------------------------------------------------------------------- */
     175               1 :     if( poOpenInfo->eAccess == GA_Update )
     176                 :     {
     177                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     178                 :                   "The MAP driver does not support update access to existing"
     179               0 :                   " datasets.\n" );
     180               0 :         return NULL;
     181                 :     }
     182                 :     
     183                 : /* -------------------------------------------------------------------- */
     184                 : /*      Create a corresponding GDALDataset.                             */
     185                 : /* -------------------------------------------------------------------- */
     186                 : 
     187               1 :     MAPDataset *poDS = new MAPDataset();
     188                 : 
     189                 : /* -------------------------------------------------------------------- */
     190                 : /*      Try to load and parse the .MAP file.                            */
     191                 : /* -------------------------------------------------------------------- */
     192                 : 
     193                 :     int bOziFileOK = 
     194                 :          GDALLoadOziMapFile( poOpenInfo->pszFilename,
     195                 :                              poDS->adfGeoTransform, 
     196                 :                              &poDS->pszWKT,
     197               1 :                              &poDS->nGCPCount, &poDS->pasGCPList );
     198                 : 
     199               2 :     if ( bOziFileOK && poDS->nGCPCount == 0 )
     200               0 :          poDS->bGeoTransformValid = TRUE;
     201                 : 
     202                 :    /* We need to read again the .map file because the GDALLoadOziMapFile function
     203                 :       does not returns all required data . An API change is necessary : maybe in GDAL 2.0 ? */
     204                 : 
     205                 :     char  **papszLines;
     206               1 :     int   iLine, nLines=0;
     207                 : 
     208               1 :     papszLines = CSLLoad2( poOpenInfo->pszFilename, 200, 200, NULL );
     209                 : 
     210               1 :     if ( !papszLines )
     211               0 :         return NULL;
     212                 : 
     213               1 :     nLines = CSLCount( papszLines );
     214               1 :     if( nLines < 2 )
     215                 :     {
     216               0 :         CSLDestroy(papszLines);
     217               0 :         return NULL;
     218                 :     }
     219                 : 
     220                 : /* -------------------------------------------------------------------- */
     221                 : /*      We need to open the image in order to establish                 */
     222                 : /*      details like the band count and types.                          */
     223                 : /* -------------------------------------------------------------------- */
     224               1 :     poDS->osImgFilename = papszLines[2];
     225                 :     VSIStatBufL sStat;
     226               1 :     if (VSIStatL(poDS->osImgFilename, &sStat) != 0)
     227                 :     {
     228               1 :         CPLString osPath = CPLGetPath(poOpenInfo->pszFilename);
     229               1 :         if (CPLIsFilenameRelative(poDS->osImgFilename))
     230                 :         {
     231               1 :             poDS->osImgFilename = CPLFormFilename(osPath, poDS->osImgFilename, NULL);
     232                 :         }
     233                 :         else
     234                 :         {
     235               0 :             poDS->osImgFilename = CPLGetFilename(poDS->osImgFilename);
     236               0 :             poDS->osImgFilename = CPLFormFilename(osPath, poDS->osImgFilename, NULL);
     237               1 :         }
     238                 :     }
     239                 : 
     240                 : /* -------------------------------------------------------------------- */
     241                 : /*      Try and open the file.                                          */
     242                 : /* -------------------------------------------------------------------- */
     243               1 :     poDS->poImageDS = (GDALDataset *) GDALOpen(poDS->osImgFilename, GA_ReadOnly );
     244               1 :     if( poDS->poImageDS == NULL || poDS->poImageDS->GetRasterCount() == 0)
     245                 :     {
     246               0 :         CSLDestroy(papszLines);
     247               0 :         delete poDS;
     248               0 :         return NULL;
     249                 :     }
     250                 : 
     251                 : /* -------------------------------------------------------------------- */
     252                 : /*      Attach the bands.                                               */
     253                 : /* -------------------------------------------------------------------- */
     254                 :     int iBand;
     255                 : 
     256               1 :     poDS->nRasterXSize = poDS->poImageDS->GetRasterXSize();
     257               1 :     poDS->nRasterYSize = poDS->poImageDS->GetRasterYSize();
     258               1 :     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
     259                 :     {
     260               0 :         delete poDS;
     261               0 :         GDALClose( poDS->poImageDS );
     262               0 :         return NULL;
     263                 :     }
     264                 : 
     265               4 :     for( iBand = 1; iBand <= poDS->poImageDS->GetRasterCount(); iBand++ )
     266                 :         poDS->SetBand( iBand,
     267               1 :                        new MAPWrapperRasterBand( poDS->poImageDS->GetRasterBand( iBand )) );
     268                 : 
     269                 : /* -------------------------------------------------------------------- */
     270                 : /*      Add the neatline/cutline, if required                           */
     271                 : /* -------------------------------------------------------------------- */
     272                 : 
     273                 :     /* First, we need to check if it is necessary to define a neatline */
     274               1 :     bool bNeatLine = false;
     275                 :     char **papszTok;
     276              36 :     for ( iLine = 10; iLine < nLines; iLine++ )
     277                 :     {
     278              36 :         if ( EQUALN(papszLines[iLine], "MMPXY,", 6) )
     279                 :         {
     280               1 :             papszTok = CSLTokenizeString2( papszLines[iLine], ",",
     281                 :                                            CSLT_STRIPLEADSPACES
     282               2 :                                            | CSLT_STRIPENDSPACES );
     283                 : 
     284               1 :             if ( CSLCount(papszTok) != 4 )
     285                 :             {
     286               0 :                 CSLDestroy(papszTok);
     287               0 :                 continue;
     288                 :             }
     289                 : 
     290               1 :             int x = CPLAtofM(papszTok[2]);
     291               1 :             int y = CPLAtofM(papszTok[3]);
     292               1 :             if (( x != 0 && x != poDS->nRasterXSize) || (y != 0 && y != poDS->nRasterYSize) )
     293                 :             {
     294               1 :                 bNeatLine = true;
     295               1 :                 CSLDestroy(papszTok);
     296               1 :                 break;
     297                 :             }
     298               0 :             CSLDestroy(papszTok);
     299                 :         }
     300                 :     }
     301                 : 
     302                 :     /* Create and fill the neatline polygon */
     303               1 :     if (bNeatLine)
     304                 :     {
     305               1 :         poDS->poNeatLine = new OGRPolygon(); /* Create a polygon to store the neatline */
     306               2 :         OGRLinearRing* poRing = new OGRLinearRing();
     307                 : 
     308               1 :         if ( poDS->bGeoTransformValid )        /* Compute the projected coordinates of the corners */
     309                 :         {
     310               0 :             for ( iLine = 10; iLine < nLines; iLine++ )
     311                 :             {
     312               0 :                 if ( EQUALN(papszLines[iLine], "MMPXY,", 6) )
     313                 :                 {
     314               0 :                     papszTok = CSLTokenizeString2( papszLines[iLine], ",",
     315                 :                                                    CSLT_STRIPLEADSPACES
     316               0 :                                                    | CSLT_STRIPENDSPACES );
     317                 : 
     318               0 :                     if ( CSLCount(papszTok) != 4 )
     319                 :                     {
     320               0 :                         CSLDestroy(papszTok);
     321               0 :                         continue;
     322                 :                     }
     323                 : 
     324               0 :                     double x = CPLAtofM(papszTok[2]);
     325               0 :                     double y = CPLAtofM(papszTok[3]);
     326               0 :                     double X = poDS->adfGeoTransform[0] + x * poDS->adfGeoTransform[1] +
     327               0 :                                             y * poDS->adfGeoTransform[2];
     328               0 :                     double Y = poDS->adfGeoTransform[3] + x * poDS->adfGeoTransform[4] +
     329               0 :                                             y * poDS->adfGeoTransform[5];
     330               0 :                     poRing->addPoint(X, Y);
     331               0 :                     CPLDebug( "CORNER MMPXY", "%f, %f, %f, %f", x, y, X, Y);
     332               0 :                     CSLDestroy(papszTok);
     333                 :                 }
     334                 :             }
     335                 :         }
     336                 :         else /* Convert the geographic coordinates to projected coordinates */
     337                 :         {
     338               1 :             OGRSpatialReference oSRS;
     339               1 :             OGRSpatialReference *poLatLong = NULL;
     340               1 :             OGRCoordinateTransformation *poTransform = NULL;
     341                 :             OGRErr eErr;
     342               1 :             char *pszWKT = poDS->pszWKT;
     343                 : 
     344               1 :             if ( &poDS->pszWKT != NULL )
     345                 :             {
     346               1 :                 eErr = oSRS.importFromWkt ( &pszWKT );
     347               1 :                 if ( eErr == OGRERR_NONE )
     348               1 :                     poLatLong = oSRS.CloneGeogCS();
     349               1 :                     if ( poLatLong )
     350               1 :                         poTransform = OGRCreateCoordinateTransformation( poLatLong, &oSRS );
     351                 :             }
     352                 : 
     353              47 :             for ( iLine = 10; iLine < nLines; iLine++ )
     354                 :             {
     355              46 :                 if ( EQUALN(papszLines[iLine], "MMPLL,", 6) )
     356                 :                 {
     357               4 :                     CPLDebug( "MMPLL", "%s", papszLines[iLine] );
     358               4 :                     char **papszTok = NULL;
     359                 : 
     360               4 :                     papszTok = CSLTokenizeString2( papszLines[iLine], ",",
     361                 :                                                    CSLT_STRIPLEADSPACES
     362               8 :                                                    | CSLT_STRIPENDSPACES );
     363                 : 
     364               4 :                     if ( CSLCount(papszTok) != 4 )
     365                 :                     {
     366               0 :                          CSLDestroy(papszTok);
     367               0 :                          continue;
     368                 :                     }
     369                 : 
     370               4 :                     double dfLon = CPLAtofM(papszTok[2]);
     371               4 :                     double dfLat = CPLAtofM(papszTok[3]);
     372                 : 
     373               4 :                     if ( poTransform )
     374               4 :                         poTransform->Transform( 1, &dfLon, &dfLat );
     375               4 :                     poRing->addPoint(dfLon, dfLat);
     376               4 :                     CPLDebug( "CORNER MMPLL", "%f, %f", dfLon, dfLat);
     377               4 :                     CSLDestroy(papszTok);
     378                 :                 }
     379                 :             }
     380               1 :             if (poTransform)
     381               1 :                 delete poTransform;
     382               1 :             if (poLatLong)
     383               1 :                 delete poLatLong;
     384                 :         }
     385                 : 
     386               1 :         poRing->closeRings();
     387               1 :         poDS->poNeatLine->addRingDirectly(poRing);
     388                 : 
     389               1 :         char* pszNeatLineWkt = NULL;
     390               1 :         poDS->poNeatLine->exportToWkt(&pszNeatLineWkt);
     391               1 :         CPLDebug( "NEATLINE", "%s", pszNeatLineWkt);
     392               1 :         poDS->SetMetadataItem("NEATLINE", pszNeatLineWkt);
     393               1 :         CPLFree(pszNeatLineWkt);
     394                 :     }
     395                 : 
     396               1 :     CSLDestroy(papszLines);
     397                 : 
     398               1 :     return( poDS );
     399                 : }
     400                 : 
     401                 : /************************************************************************/
     402                 : /*                          GetProjectionRef()                          */
     403                 : /************************************************************************/
     404                 : 
     405               0 : const char* MAPDataset::GetProjectionRef()
     406                 : {
     407               0 :     return (pszWKT && nGCPCount == 0) ? pszWKT : "";
     408                 : }
     409                 : 
     410                 : /************************************************************************/
     411                 : /*                          GetGeoTransform()                           */
     412                 : /************************************************************************/
     413                 : 
     414               0 : CPLErr MAPDataset::GetGeoTransform( double * padfTransform )
     415                 : 
     416                 : {
     417               0 :     memcpy(padfTransform, adfGeoTransform, 6 * sizeof(double));
     418                 : 
     419               0 :     return( (nGCPCount == 0) ? CE_None : CE_Failure );
     420                 : }
     421                 : 
     422                 : 
     423                 : /************************************************************************/
     424                 : /*                           GetGCPCount()                              */
     425                 : /************************************************************************/
     426                 : 
     427               1 : int MAPDataset::GetGCPCount()
     428                 : {
     429               1 :     return nGCPCount;
     430                 : }
     431                 : 
     432                 : /************************************************************************/
     433                 : /*                          GetGCPProjection()                          */
     434                 : /************************************************************************/
     435                 : 
     436               1 : const char * MAPDataset::GetGCPProjection()
     437                 : {
     438               1 :     return (pszWKT && nGCPCount != 0) ? pszWKT : "";
     439                 : }
     440                 : 
     441                 : /************************************************************************/
     442                 : /*                               GetGCPs()                              */
     443                 : /************************************************************************/
     444                 : 
     445               1 : const GDAL_GCP * MAPDataset::GetGCPs()
     446                 : {
     447               1 :     return pasGCPList;
     448                 : }
     449                 : 
     450                 : /************************************************************************/
     451                 : /*                            GetFileList()                             */
     452                 : /************************************************************************/
     453                 : 
     454               0 : char** MAPDataset::GetFileList()
     455                 : {
     456               0 :     char **papszFileList = GDALDataset::GetFileList();
     457                 : 
     458               0 :     papszFileList = CSLAddString( papszFileList, osImgFilename );
     459                 :     
     460               0 :     return papszFileList;
     461                 : }
     462                 : 
     463                 : /************************************************************************/
     464                 : /*                          GDALRegister_MAP()                          */
     465                 : /************************************************************************/
     466                 : 
     467             582 : void GDALRegister_MAP()
     468                 : 
     469                 : {
     470                 :     GDALDriver  *poDriver;
     471                 : 
     472             582 :     if( GDALGetDriverByName( "MAP" ) == NULL )
     473                 :     {
     474             561 :         poDriver = new GDALDriver();
     475                 :         
     476             561 :         poDriver->SetDescription( "MAP" );
     477                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
     478             561 :                                    "OziExplorer .MAP" );
     479                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
     480             561 :                                    "frmt_map.html" );
     481                 : 
     482             561 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
     483                 : 
     484             561 :         poDriver->pfnOpen = MAPDataset::Open;
     485             561 :         poDriver->pfnIdentify = MAPDataset::Identify;
     486                 : 
     487             561 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     488                 :     }
     489             582 : }
     490                 : 
     491                 : 

Generated by: LCOV version 1.7