LCOV - code coverage report
Current view: directory - frmts/xyz - xyzdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 431 339 78.7 %
Date: 2012-04-28 Functions: 16 11 68.8 %

       1                 : /******************************************************************************
       2                 :  * $Id: xyzdataset.cpp 22596 2011-06-27 18:53:18Z rouault $
       3                 :  *
       4                 :  * Project:  XYZ driver
       5                 :  * Purpose:  GDALDataset driver for XYZ dataset.
       6                 :  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2010, Even Rouault
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "cpl_vsi_virtual.h"
      31                 : #include "cpl_string.h"
      32                 : #include "gdal_pam.h"
      33                 : 
      34                 : CPL_CVSID("$Id: xyzdataset.cpp 22596 2011-06-27 18:53:18Z rouault $");
      35                 : 
      36                 : CPL_C_START
      37                 : void    GDALRegister_XYZ(void);
      38                 : CPL_C_END
      39                 : 
      40                 : /************************************************************************/
      41                 : /* ==================================================================== */
      42                 : /*                              XYZDataset                              */
      43                 : /* ==================================================================== */
      44                 : /************************************************************************/
      45                 : 
      46                 : class XYZRasterBand;
      47                 : 
      48                 : class XYZDataset : public GDALPamDataset
      49                 : {
      50                 :     friend class XYZRasterBand;
      51                 :     
      52                 :     VSILFILE   *fp;
      53                 :     int         bHasHeaderLine;
      54                 :     int         nCommentLineCount;
      55                 :     int         nXIndex;
      56                 :     int         nYIndex;
      57                 :     int         nZIndex;
      58                 :     int         nMinTokens;
      59                 :     int         nLineNum;     /* any line */
      60                 :     int         nDataLineNum; /* line with values (header line and empty lines ignored) */
      61                 :     double      adfGeoTransform[6];
      62                 :     
      63                 :     static int          IdentifyEx( GDALOpenInfo *, int&, int& nCommentLineCount );
      64                 : 
      65                 :   public:
      66                 :                  XYZDataset();
      67                 :     virtual     ~XYZDataset();
      68                 :     
      69                 :     virtual CPLErr GetGeoTransform( double * );
      70                 :     
      71                 :     static GDALDataset *Open( GDALOpenInfo * );
      72                 :     static int          Identify( GDALOpenInfo * );
      73                 :     static GDALDataset *CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
      74                 :                                     int bStrict, char ** papszOptions, 
      75                 :                                     GDALProgressFunc pfnProgress, void * pProgressData );
      76                 : };
      77                 : 
      78                 : /************************************************************************/
      79                 : /* ==================================================================== */
      80                 : /*                            XYZRasterBand                             */
      81                 : /* ==================================================================== */
      82                 : /************************************************************************/
      83                 : 
      84                 : class XYZRasterBand : public GDALPamRasterBand
      85              36 : {
      86                 :     friend class XYZDataset;
      87                 : 
      88                 :   public:
      89                 : 
      90                 :                 XYZRasterBand( XYZDataset *, int, GDALDataType );
      91                 : 
      92                 :     virtual CPLErr IReadBlock( int, int, void * );
      93                 : };
      94                 : 
      95                 : 
      96                 : /************************************************************************/
      97                 : /*                           XYZRasterBand()                            */
      98                 : /************************************************************************/
      99                 : 
     100              36 : XYZRasterBand::XYZRasterBand( XYZDataset *poDS, int nBand, GDALDataType eDT )
     101                 : 
     102                 : {
     103              36 :     this->poDS = poDS;
     104              36 :     this->nBand = nBand;
     105                 : 
     106              36 :     eDataType = eDT;
     107                 : 
     108              36 :     nBlockXSize = poDS->GetRasterXSize();
     109              36 :     nBlockYSize = 1;
     110              36 : }
     111                 : 
     112                 : /************************************************************************/
     113                 : /*                             IReadBlock()                             */
     114                 : /************************************************************************/
     115                 : 
     116             890 : CPLErr XYZRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     117                 :                                   void * pImage )
     118                 : 
     119                 : {
     120             890 :     XYZDataset *poGDS = (XYZDataset *) poDS;
     121                 :     
     122             890 :     if (poGDS->fp == NULL)
     123               0 :         return CE_Failure;
     124                 : 
     125             890 :     int nLineInFile = nBlockYOff * nBlockXSize;
     126             890 :     if (poGDS->nDataLineNum > nLineInFile)
     127                 :     {
     128              14 :         poGDS->nDataLineNum = 0;
     129              14 :         VSIFSeekL(poGDS->fp, 0, SEEK_SET);
     130                 : 
     131              14 :         for(int i=0;i<poGDS->nCommentLineCount;i++)
     132               0 :             CPLReadLine2L(poGDS->fp, 100, NULL);
     133                 : 
     134              14 :         if (poGDS->bHasHeaderLine)
     135                 :         {
     136              10 :             const char* pszLine = CPLReadLine2L(poGDS->fp, 100, 0);
     137              10 :             if (pszLine == NULL)
     138                 :             {
     139               0 :                 memset(pImage, 0, nBlockXSize * (GDALGetDataTypeSize(eDataType) / 8));
     140               0 :                 return CE_Failure;
     141                 :             }
     142              10 :             poGDS->nLineNum ++;
     143                 :         }
     144                 :     }
     145                 : 
     146            1804 :     while(poGDS->nDataLineNum < nLineInFile)
     147                 :     {
     148              24 :         const char* pszLine = CPLReadLine2L(poGDS->fp, 100, 0);
     149              24 :         if (pszLine == NULL)
     150                 :         {
     151               0 :             memset(pImage, 0, nBlockXSize * (GDALGetDataTypeSize(eDataType) / 8));
     152               0 :             return CE_Failure;
     153                 :         }
     154              24 :         poGDS->nLineNum ++;
     155                 : 
     156              24 :         const char* pszPtr = pszLine;
     157                 :         char ch;
     158              24 :         int nCol = 0;
     159              24 :         int bLastWasSep = TRUE;
     160             120 :         while((ch = *pszPtr) != '\0')
     161                 :         {
     162              96 :             if (ch == ' ' || ch == ',' || ch == '\t' || ch == ';')
     163                 :             {
     164              24 :                 if (!bLastWasSep)
     165              24 :                     nCol ++;
     166              24 :                 bLastWasSep = TRUE;
     167                 :             }
     168                 :             else
     169                 :             {
     170              48 :                 bLastWasSep = FALSE;
     171                 :             }
     172              72 :             pszPtr ++;
     173                 :         }
     174                 : 
     175                 :         /* Skip empty line */
     176              24 :         if (nCol == 0 && bLastWasSep)
     177              12 :             continue;
     178                 : 
     179              12 :         poGDS->nDataLineNum ++;
     180                 :     }
     181                 : 
     182                 :     int i;
     183          164106 :     for(i=0;i<nBlockXSize;i++)
     184                 :     {
     185                 :         int nCol;
     186                 :         int bLastWasSep;
     187          163224 :         do
     188                 :         {
     189          163224 :             const char* pszLine = CPLReadLine2L(poGDS->fp, 100, 0);
     190          163224 :             if (pszLine == NULL)
     191                 :             {
     192               0 :                 memset(pImage, 0, nBlockXSize * (GDALGetDataTypeSize(eDataType) / 8));
     193               0 :                 return CE_Failure;
     194                 :             }
     195          163224 :             poGDS->nLineNum ++;
     196                 : 
     197          163224 :             const char* pszPtr = pszLine;
     198                 :             char ch;
     199          163224 :             nCol = 0;
     200          163224 :             bLastWasSep = TRUE;
     201         5598096 :             while((ch = *pszPtr) != '\0')
     202                 :             {
     203         5598080 :                 if (ch == ' ' || ch == ',' || ch == '\t' || ch == ';')
     204                 :                 {
     205          326432 :                     if (!bLastWasSep)
     206          326432 :                         nCol ++;
     207          326432 :                     bLastWasSep = TRUE;
     208                 :                 }
     209                 :                 else
     210                 :                 {
     211         4945216 :                     if (bLastWasSep && nCol == poGDS->nZIndex)
     212                 :                     {
     213          163216 :                         double dfZ = CPLAtofM(pszPtr);
     214          163216 :                         if (eDataType == GDT_Float32)
     215                 :                         {
     216          161604 :                             ((float*)pImage)[i] = (float)dfZ;
     217                 :                         }
     218            1612 :                         else if (eDataType == GDT_Int32)
     219                 :                         {
     220               0 :                             ((GInt32*)pImage)[i] = (GInt32)dfZ;
     221                 :                         }
     222            1612 :                         else if (eDataType == GDT_Int16)
     223                 :                         {
     224               0 :                             ((GInt16*)pImage)[i] = (GInt16)dfZ;
     225                 :                         }
     226                 :                         else
     227                 :                         {
     228            1612 :                             ((GByte*)pImage)[i] = (GByte)dfZ;
     229                 :                         }
     230                 :                     }
     231         4945216 :                     bLastWasSep = FALSE;
     232                 :                 }
     233         5271648 :                 pszPtr ++;
     234                 :             }
     235                 : 
     236                 :             /* Skip empty line */
     237                 :         }
     238                 :         while (nCol == 0 && bLastWasSep);
     239                 : 
     240          163216 :         poGDS->nDataLineNum ++;
     241          163216 :         nCol ++;
     242          163216 :         if (nCol < poGDS->nMinTokens)
     243                 :         {
     244               0 :             memset(pImage, 0, nBlockXSize * (GDALGetDataTypeSize(eDataType) / 8));
     245               0 :             return CE_Failure;
     246                 :         }
     247                 :     }
     248             890 :     CPLAssert(poGDS->nDataLineNum == (nBlockYOff + 1) * nBlockXSize);
     249                 : 
     250             890 :     return CE_None;
     251                 : }
     252                 : 
     253                 : /************************************************************************/
     254                 : /*                            ~XYZDataset()                            */
     255                 : /************************************************************************/
     256                 : 
     257              36 : XYZDataset::XYZDataset()
     258                 : {
     259              36 :     fp = NULL;
     260              36 :     nDataLineNum = INT_MAX;
     261              36 :     nLineNum = 0;
     262              36 :     bHasHeaderLine = FALSE;
     263              36 :     nXIndex = -1;
     264              36 :     nYIndex = -1;
     265              36 :     nZIndex = -1;
     266              36 :     nMinTokens = 0;
     267              36 :     adfGeoTransform[0] = 0;
     268              36 :     adfGeoTransform[1] = 1;
     269              36 :     adfGeoTransform[2] = 0;
     270              36 :     adfGeoTransform[3] = 0;
     271              36 :     adfGeoTransform[4] = 0;
     272              36 :     adfGeoTransform[5] = 1;
     273              36 : }
     274                 : 
     275                 : /************************************************************************/
     276                 : /*                            ~XYZDataset()                            */
     277                 : /************************************************************************/
     278                 : 
     279              36 : XYZDataset::~XYZDataset()
     280                 : 
     281                 : {
     282              36 :     FlushCache();
     283              36 :     if (fp)
     284              36 :         VSIFCloseL(fp);
     285              36 : }
     286                 : 
     287                 : /************************************************************************/
     288                 : /*                             Identify()                               */
     289                 : /************************************************************************/
     290                 : 
     291           18894 : int XYZDataset::Identify( GDALOpenInfo * poOpenInfo )
     292                 : {
     293                 :     int bHasHeaderLine, nCommentLineCount;
     294           18894 :     return IdentifyEx(poOpenInfo, bHasHeaderLine, nCommentLineCount);
     295                 : }
     296                 : 
     297                 : /************************************************************************/
     298                 : /*                            IdentifyEx()                              */
     299                 : /************************************************************************/
     300                 : 
     301                 : 
     302           21904 : int XYZDataset::IdentifyEx( GDALOpenInfo * poOpenInfo,
     303                 :                             int& bHasHeaderLine,
     304                 :                             int& nCommentLineCount)
     305                 : 
     306                 : {
     307                 :     int         i;
     308                 : 
     309           21904 :     bHasHeaderLine = FALSE;
     310           21904 :     nCommentLineCount = 0;
     311                 : 
     312           21904 :     CPLString osFilename(poOpenInfo->pszFilename);
     313                 : 
     314           21904 :     GDALOpenInfo* poOpenInfoToDelete = NULL;
     315                 :     /*  GZipped .xyz files are common, so automagically open them */
     316                 :     /*  if the /vsigzip/ has not been explicitely passed */
     317           21904 :     if (strlen(poOpenInfo->pszFilename) > 6 &&
     318                 :         EQUAL(poOpenInfo->pszFilename + strlen(poOpenInfo->pszFilename) - 6, "xyz.gz") &&
     319                 :         !EQUALN(poOpenInfo->pszFilename, "/vsigzip/", 9))
     320                 :     {
     321               0 :         osFilename = "/vsigzip/";
     322               0 :         osFilename += poOpenInfo->pszFilename;
     323                 :         poOpenInfo = poOpenInfoToDelete =
     324                 :                 new GDALOpenInfo(osFilename.c_str(), GA_ReadOnly,
     325               0 :                                  poOpenInfo->papszSiblingFiles);
     326                 :     }
     327                 : 
     328           21904 :     if (poOpenInfo->nHeaderBytes == 0)
     329                 :     {
     330           21140 :         delete poOpenInfoToDelete;
     331           21140 :         return FALSE;
     332                 :     }
     333                 : 
     334                 : /* -------------------------------------------------------------------- */
     335                 : /*      Chech that it looks roughly as a XYZ dataset                    */
     336                 : /* -------------------------------------------------------------------- */
     337             764 :     const char* pszData = (const char*)poOpenInfo->pabyHeader;
     338                 : 
     339                 :     /* Skip comments line at the beginning such as in */
     340                 :     /* http://pubs.usgs.gov/of/2003/ofr-03-230/DATA/NSLCU.XYZ */
     341             764 :     i=0;
     342             764 :     if (pszData[i] == '/')
     343                 :     {
     344               0 :         nCommentLineCount ++;
     345                 : 
     346               0 :         i++;
     347               0 :         for(;i<poOpenInfo->nHeaderBytes;i++)
     348                 :         {
     349               0 :             char ch = pszData[i];
     350               0 :             if (ch == 13 || ch == 10)
     351                 :             {
     352               0 :                 if (ch == 13 && pszData[i+1] == 10)
     353               0 :                     i++;
     354               0 :                 if (pszData[i+1] == '/')
     355                 :                 {
     356               0 :                     nCommentLineCount ++;
     357               0 :                     i++;
     358                 :                 }
     359                 :                 else
     360               0 :                     break;
     361                 :             }
     362                 :         }
     363                 :     }
     364                 : 
     365           29022 :     for(;i<poOpenInfo->nHeaderBytes;i++)
     366                 :     {
     367           28994 :         char ch = pszData[i];
     368           28994 :         if (ch == 13 || ch == 10)
     369                 :         {
     370              38 :             break;
     371                 :         }
     372           28956 :         else if (ch == ' ' || ch == ',' || ch == '\t' || ch == ';')
     373                 :             ;
     374            3180 :         else if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '+' ||
     375                 :                  ch == '-' || ch == 'e' || ch == 'E')
     376                 :             ;
     377            1706 :         else if (ch == '"' || (ch >= 'a' && ch <= 'z') ||
     378                 :                               (ch >= 'A' && ch <= 'Z'))
     379             504 :             bHasHeaderLine = TRUE;
     380                 :         else
     381                 :         {
     382             698 :             delete poOpenInfoToDelete;
     383             698 :             return FALSE;
     384                 :         }
     385                 :     }
     386              66 :     int bHasFoundNewLine = FALSE;
     387              66 :     int bPrevWasSep = TRUE;
     388              66 :     int nCols = 0;
     389              66 :     int nMaxCols = 0;
     390           33902 :     for(;i<poOpenInfo->nHeaderBytes;i++)
     391                 :     {
     392           33838 :         char ch = pszData[i];
     393           35080 :         if (ch == 13 || ch == 10)
     394                 :         {
     395            1242 :             bHasFoundNewLine = TRUE;
     396            1242 :             if (!bPrevWasSep)
     397                 :             {
     398            1190 :                 nCols ++;
     399            1190 :                 if (nCols > nMaxCols)
     400              36 :                     nMaxCols = nCols;
     401                 :             }
     402            1242 :             bPrevWasSep = TRUE;
     403            1242 :             nCols = 0;
     404                 :         }
     405           35004 :         else if (ch == ' ' || ch == ',' || ch == '\t' || ch == ';')
     406                 :         {
     407            2408 :             if (!bPrevWasSep)
     408                 :             {
     409            2408 :                 nCols ++;
     410            2408 :                 if (nCols > nMaxCols)
     411              72 :                     nMaxCols = nCols;
     412                 :             }
     413            2408 :             bPrevWasSep = TRUE;
     414                 :         }
     415           60374 :         else if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '+' ||
     416                 :                  ch == '-' || ch == 'e' || ch == 'E')
     417                 :         {
     418           30186 :             bPrevWasSep = FALSE;
     419                 :         }
     420                 :         else
     421                 :         {
     422               2 :             delete poOpenInfoToDelete;
     423               2 :             return FALSE;
     424                 :         }
     425                 :     }
     426                 : 
     427              64 :     delete poOpenInfoToDelete;
     428              64 :     return bHasFoundNewLine && nMaxCols >= 3;
     429                 : }
     430                 : 
     431                 : /************************************************************************/
     432                 : /*                                Open()                                */
     433                 : /************************************************************************/
     434                 : 
     435            3010 : GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
     436                 : 
     437                 : {
     438                 :     int         i;
     439                 :     int         bHasHeaderLine;
     440            3010 :     int         nCommentLineCount = 0;
     441                 : 
     442            3010 :     if (!IdentifyEx(poOpenInfo, bHasHeaderLine, nCommentLineCount))
     443            2974 :         return NULL;
     444                 : 
     445              36 :     CPLString osFilename(poOpenInfo->pszFilename);
     446                 : 
     447                 :     /*  GZipped .xyz files are common, so automagically open them */
     448                 :     /*  if the /vsigzip/ has not been explicitely passed */
     449              36 :     if (strlen(poOpenInfo->pszFilename) > 6 &&
     450                 :         EQUAL(poOpenInfo->pszFilename + strlen(poOpenInfo->pszFilename) - 6, "xyz.gz") &&
     451                 :         !EQUALN(poOpenInfo->pszFilename, "/vsigzip/", 9))
     452                 :     {
     453               0 :         osFilename = "/vsigzip/";
     454               0 :         osFilename += poOpenInfo->pszFilename;
     455                 :     }
     456                 : 
     457                 : /* -------------------------------------------------------------------- */
     458                 : /*      Find dataset characteristics                                    */
     459                 : /* -------------------------------------------------------------------- */
     460              36 :     VSILFILE* fp = VSIFOpenL(osFilename.c_str(), "rb");
     461              36 :     if (fp == NULL)
     462               0 :         return NULL;
     463                 : 
     464                 :     /* For better performance of CPLReadLine2L() we create a buffered reader */
     465                 :     /* (except for /vsigzip/ since it has one internally) */
     466              36 :     if (!EQUALN(poOpenInfo->pszFilename, "/vsigzip/", 9))
     467              36 :         fp = (VSILFILE*) VSICreateBufferedReaderHandle((VSIVirtualHandle*)fp);
     468                 :     
     469                 :     const char* pszLine;
     470              36 :     int nXIndex = -1, nYIndex = -1, nZIndex = -1;
     471              36 :     int nMinTokens = 0;
     472                 : 
     473                 : 
     474              36 :     for(i=0;i<nCommentLineCount;i++)
     475               0 :         CPLReadLine2L(fp, 100, NULL);
     476                 : 
     477                 : /* -------------------------------------------------------------------- */
     478                 : /*      Parse header line                                               */
     479                 : /* -------------------------------------------------------------------- */
     480              36 :     if (bHasHeaderLine)
     481                 :     {
     482               8 :         pszLine = CPLReadLine2L(fp, 100, NULL);
     483               8 :         if (pszLine == NULL)
     484                 :         {
     485               0 :             VSIFCloseL(fp);
     486               0 :             return NULL;
     487                 :         }
     488                 :         char** papszTokens = CSLTokenizeString2( pszLine, " ,\t;",
     489               8 :                                                  CSLT_HONOURSTRINGS );
     490               8 :         int nTokens = CSLCount(papszTokens);
     491               8 :         if (nTokens < 3)
     492                 :         {
     493                 :             CPLError(CE_Failure, CPLE_AppDefined,
     494                 :                      "At line %d, found %d tokens. Expected 3 at least",
     495               0 :                       1, nTokens);
     496               0 :             CSLDestroy(papszTokens);
     497               0 :             VSIFCloseL(fp);
     498               0 :             return NULL;
     499                 :         }
     500                 :         int i;
     501              32 :         for(i=0;i<nTokens;i++)
     502                 :         {
     503              64 :             if (EQUAL(papszTokens[i], "x") ||
     504              16 :                 EQUALN(papszTokens[i], "lon", 3) ||
     505              16 :                 EQUALN(papszTokens[i], "east", 4))
     506               8 :                 nXIndex = i;
     507              40 :             else if (EQUAL(papszTokens[i], "y") ||
     508               8 :                      EQUALN(papszTokens[i], "lat", 3) ||
     509               8 :                      EQUALN(papszTokens[i], "north", 5))
     510               8 :                 nYIndex = i;
     511               8 :             else if (EQUAL(papszTokens[i], "z") ||
     512               0 :                      EQUALN(papszTokens[i], "alt", 3) ||
     513               0 :                      EQUAL(papszTokens[i], "height"))
     514               8 :                 nZIndex = i;
     515                 :         }
     516               8 :         CSLDestroy(papszTokens);
     517               8 :         papszTokens = NULL;
     518               8 :         if (nXIndex < 0 || nYIndex < 0 || nZIndex < 0)
     519                 :         {
     520                 :             CPLError(CE_Warning, CPLE_AppDefined,
     521               0 :                      "Could not find one of the X, Y or Z column names in header line. Defaulting to the first 3 columns");
     522               0 :             nXIndex = 0;
     523               0 :             nYIndex = 1;
     524               0 :             nZIndex = 2;
     525                 :         }
     526               8 :         nMinTokens = 1 + MAX(MAX(nXIndex, nYIndex), nZIndex);
     527                 :     }
     528                 :     else
     529                 :     {
     530              28 :         nXIndex = 0;
     531              28 :         nYIndex = 1;
     532              28 :         nZIndex = 2;
     533              28 :         nMinTokens = 3;
     534                 :     }
     535                 :     
     536                 : /* -------------------------------------------------------------------- */
     537                 : /*      Parse data lines                                                */
     538                 : /* -------------------------------------------------------------------- */
     539                 : 
     540              36 :     int nXSize = 0, nYSize = 0;
     541              36 :     int nLineNum = 0;
     542              36 :     int nDataLineNum = 0;
     543              36 :     double dfFirstX = 0;
     544              36 :     double dfX = 0, dfY = 0, dfZ = 0;
     545              36 :     double dfMinX = 0, dfMinY = 0, dfMaxX = 0, dfMaxY = 0;
     546              36 :     double dfLastX = 0, dfLastY = 0;
     547              36 :     double dfStepX = 0, dfStepY = 0;
     548              36 :     GDALDataType eDT = GDT_Byte;
     549          247102 :     while((pszLine = CPLReadLine2L(fp, 100, NULL)) != NULL)
     550                 :     {
     551          247030 :         nLineNum ++;
     552                 : 
     553          247030 :         const char* pszPtr = pszLine;
     554                 :         char ch;
     555          247030 :         int nCol = 0;
     556          247030 :         int bLastWasSep = TRUE;
     557         8483336 :         while((ch = *pszPtr) != '\0')
     558                 :         {
     559         8483312 :             if (ch == ' ' || ch == ',' || ch == '\t' || ch == ';')
     560                 :             {
     561          494036 :                 if (!bLastWasSep)
     562          494036 :                     nCol ++;
     563          494036 :                 bLastWasSep = TRUE;
     564                 :             }
     565                 :             else
     566                 :             {
     567         7495240 :                 if (bLastWasSep)
     568                 :                 {
     569          741054 :                     if (nCol == nXIndex)
     570          247018 :                         dfX = CPLAtofM(pszPtr);
     571          494036 :                     else if (nCol == nYIndex)
     572          247018 :                         dfY = CPLAtofM(pszPtr);
     573          247018 :                     else if (nCol == nZIndex && eDT != GDT_Float32)
     574                 :                     {
     575           30262 :                         dfZ = CPLAtofM(pszPtr);
     576           30262 :                         int nZ = (int)dfZ;
     577           30262 :                         if ((double)nZ != dfZ)
     578                 :                         {
     579               6 :                             eDT = GDT_Float32;
     580                 :                         }
     581           30256 :                         else if ((eDT == GDT_Byte || eDT == GDT_Int16) && (nZ < 0 || nZ > 255))
     582                 :                         {
     583               0 :                             if (nZ < -32768 || nZ > 32767)
     584               0 :                                 eDT = GDT_Int32;
     585                 :                             else
     586               0 :                                 eDT = GDT_Int16;
     587                 :                         }
     588                 :                     }
     589                 :                 }
     590         7495240 :                 bLastWasSep = FALSE;
     591                 :             }
     592         7989276 :             pszPtr ++;
     593                 :         }
     594                 :         /* skip empty lines */
     595          247030 :         if (bLastWasSep && nCol == 0)
     596                 :         {
     597              12 :             continue;
     598                 :         }
     599          247018 :         nDataLineNum ++;
     600          247018 :         nCol ++;
     601          247018 :         if (nCol < nMinTokens)
     602                 :         {
     603                 :             CPLError(CE_Failure, CPLE_AppDefined,
     604                 :                      "At line %d, found %d tokens. Expected %d at least",
     605               0 :                       nLineNum, nCol, nMinTokens);
     606               0 :             VSIFCloseL(fp);
     607               0 :             return NULL;
     608                 :         }
     609                 : 
     610          247018 :         if (nDataLineNum == 1)
     611                 :         {
     612              36 :             dfFirstX = dfMinX = dfMaxX = dfX;
     613              36 :             dfMinY = dfMaxY = dfY;
     614                 :         }
     615                 :         else
     616                 :         {
     617          246982 :             if (dfX < dfMinX) dfMinX = dfX;
     618          246982 :             if (dfX > dfMaxX) dfMaxX = dfX;
     619          246982 :             if (dfY < dfMinY) dfMinY = dfY;
     620          246982 :             if (dfY > dfMaxY) dfMaxY = dfY;
     621                 :         }
     622          247018 :         if (nDataLineNum == 2)
     623                 :         {
     624              36 :             dfStepX = dfX - dfLastX;
     625              36 :             if (dfStepX <= 0)
     626                 :             {
     627                 :                 CPLError(CE_Failure, CPLE_AppDefined,
     628                 :                          "Ungridded dataset: At line %d, X spacing was %f. Expected >0 value",
     629               0 :                          nLineNum, dfStepX);
     630               0 :                 VSIFCloseL(fp);
     631               0 :                 return NULL;
     632                 :             }
     633                 :         }
     634          246982 :         else if (nDataLineNum > 2)
     635                 :         {
     636          246946 :             double dfNewStepX = dfX - dfLastX;
     637          246946 :             double dfNewStepY = dfY - dfLastY;
     638          246946 :             if (dfNewStepY != 0)
     639                 :             {
     640            1516 :                 nYSize ++;
     641            1516 :                 if (dfStepY == 0)
     642                 :                 {
     643              36 :                     nXSize = nDataLineNum - 1;
     644              36 :                     double dfAdjustedStepX = (dfMaxX - dfMinX) / (nXSize - 1);
     645              36 :                     if (fabs(dfStepX - dfAdjustedStepX) > 1e-8)
     646                 :                     {
     647               0 :                         CPLDebug("XYZ", "Adjusting stepx from %f to %f", dfStepX, dfAdjustedStepX);
     648                 :                     }
     649              36 :                     dfStepX = dfAdjustedStepX;
     650                 :                 }
     651            1516 :                 if (dfStepY != 0 && fabs(dfX - dfFirstX) > 1e-8)
     652                 :                 {
     653                 :                     CPLError(CE_Failure, CPLE_AppDefined,
     654                 :                              "Ungridded dataset: At line %d, X is %f, where as %f was expected",
     655               0 :                              nLineNum, dfX, dfFirstX);
     656               0 :                     VSIFCloseL(fp);
     657               0 :                     return NULL;
     658                 :                 }
     659            1516 :                 if (dfStepY != 0 && fabs(dfLastX - dfMaxX) > 1e-8)
     660                 :                 {
     661                 :                     CPLError(CE_Failure, CPLE_AppDefined,
     662                 :                              "Ungridded dataset: At line %d, X is %f, where as %f was expected",
     663               0 :                              nLineNum - 1, dfLastX, dfMaxX);
     664               0 :                     VSIFCloseL(fp);
     665               0 :                     return NULL;
     666                 :                 }
     667                 :                 /*if (dfStepY != 0 && fabs(dfNewStepY - dfStepY) > 1e-8)
     668                 :                 {
     669                 :                     CPLError(CE_Failure, CPLE_AppDefined,
     670                 :                              "Ungridded dataset: At line %d, Y spacing was %f, whereas it was %f before",
     671                 :                              nLineNum, dfNewStepY, dfStepY);
     672                 :                     VSIFCloseL(fp);
     673                 :                     return NULL;
     674                 :                 }*/
     675            1516 :                 dfStepY = dfNewStepY;
     676                 :             }
     677                 :             else if (dfNewStepX != 0)
     678                 :             {
     679                 :                 /*if (dfStepX != 0 && fabs(dfNewStepX - dfStepX) > 1e-8)
     680                 :                 {
     681                 :                     CPLError(CE_Failure, CPLE_AppDefined,
     682                 :                              "At line %d, X spacing was %f, whereas it was %f before",
     683                 :                              nLineNum, dfNewStepX, dfStepX);
     684                 :                     VSIFCloseL(fp);
     685                 :                     return NULL;
     686                 :                 }*/
     687                 :             }
     688                 :         }
     689          247018 :         dfLastX = dfX;
     690          247018 :         dfLastY = dfY;
     691                 :     }
     692              36 :     nYSize ++;
     693                 : 
     694              36 :     if (dfStepX == 0)
     695                 :     {
     696               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Couldn't determine X spacing");
     697               0 :         VSIFCloseL(fp);
     698               0 :         return NULL;
     699                 :     }
     700                 : 
     701              36 :     if (dfStepY == 0)
     702                 :     {
     703               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Couldn't determine Y spacing");
     704               0 :         VSIFCloseL(fp);
     705               0 :         return NULL;
     706                 :     }
     707                 : 
     708              36 :     double dfAdjustedStepY = ((dfStepY < 0) ? -1 : 1) * (dfMaxY - dfMinY) / (nYSize - 1);
     709              36 :     if (fabs(dfStepY - dfAdjustedStepY) > 1e-8)
     710                 :     {
     711               0 :         CPLDebug("XYZ", "Adjusting stepy from %f to %f", dfStepY, dfAdjustedStepY);
     712                 :     }
     713              36 :     dfStepY = dfAdjustedStepY;
     714                 : 
     715                 :     //CPLDebug("XYZ", "minx=%f maxx=%f stepx=%f", dfMinX, dfMaxX, dfStepX);
     716                 :     //CPLDebug("XYZ", "miny=%f maxy=%f stepy=%f", dfMinY, dfMaxY, dfStepY);
     717                 : 
     718              36 :     if (nDataLineNum != nXSize * nYSize)
     719                 :     {
     720                 :         CPLError(CE_Failure, CPLE_AppDefined, "Found %d lines. Expected %d",
     721               0 :                  nDataLineNum,nXSize * nYSize);
     722               0 :         VSIFCloseL(fp);
     723               0 :         return NULL;
     724                 :     }
     725                 :     
     726              36 :     if (poOpenInfo->eAccess == GA_Update)
     727                 :     {
     728                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     729                 :                   "The XYZ driver does not support update access to existing"
     730               0 :                   " datasets.\n" );
     731               0 :         VSIFCloseL(fp);
     732               0 :         return NULL;
     733                 :     }
     734                 : 
     735                 : /* -------------------------------------------------------------------- */
     736                 : /*      Create a corresponding GDALDataset.                             */
     737                 : /* -------------------------------------------------------------------- */
     738                 :     XYZDataset         *poDS;
     739                 : 
     740              36 :     poDS = new XYZDataset();
     741              36 :     poDS->fp = fp;
     742              36 :     poDS->bHasHeaderLine = bHasHeaderLine;
     743              36 :     poDS->nCommentLineCount = nCommentLineCount;
     744              36 :     poDS->nXIndex = nXIndex;
     745              36 :     poDS->nYIndex = nYIndex;
     746              36 :     poDS->nZIndex = nZIndex;
     747              36 :     poDS->nMinTokens = nMinTokens;
     748              36 :     poDS->nRasterXSize = nXSize;
     749              36 :     poDS->nRasterYSize = nYSize;
     750              36 :     poDS->adfGeoTransform[0] = dfMinX - dfStepX / 2;
     751              36 :     poDS->adfGeoTransform[1] = dfStepX;
     752                 :     poDS->adfGeoTransform[3] = (dfStepY < 0) ? dfMaxY - dfStepY / 2 :
     753              70 :                                                dfMinY - dfStepY / 2;
     754              36 :     poDS->adfGeoTransform[5] = dfStepY;
     755                 : 
     756              36 :     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
     757                 :     {
     758               0 :         delete poDS;
     759               0 :         return NULL;
     760                 :     }
     761                 : 
     762                 : /* -------------------------------------------------------------------- */
     763                 : /*      Create band information objects.                                */
     764                 : /* -------------------------------------------------------------------- */
     765              36 :     poDS->nBands = 1;
     766              72 :     for( i = 0; i < poDS->nBands; i++ )
     767              36 :         poDS->SetBand( i+1, new XYZRasterBand( poDS, i+1, eDT ) );
     768                 : 
     769                 : /* -------------------------------------------------------------------- */
     770                 : /*      Initialize any PAM information.                                 */
     771                 : /* -------------------------------------------------------------------- */
     772              36 :     poDS->SetDescription( poOpenInfo->pszFilename );
     773              36 :     poDS->TryLoadXML();
     774                 : 
     775                 : /* -------------------------------------------------------------------- */
     776                 : /*      Support overviews.                                              */
     777                 : /* -------------------------------------------------------------------- */
     778              36 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     779              36 :     return( poDS );
     780                 : }
     781                 : 
     782                 : /************************************************************************/
     783                 : /*                             CreateCopy()                             */
     784                 : /************************************************************************/
     785                 : 
     786              40 : GDALDataset* XYZDataset::CreateCopy( const char * pszFilename,
     787                 :                                      GDALDataset *poSrcDS, 
     788                 :                                      int bStrict, char ** papszOptions, 
     789                 :                                      GDALProgressFunc pfnProgress,
     790                 :                                      void * pProgressData )
     791                 : {
     792                 : /* -------------------------------------------------------------------- */
     793                 : /*      Some some rudimentary checks                                    */
     794                 : /* -------------------------------------------------------------------- */
     795              40 :     int nBands = poSrcDS->GetRasterCount();
     796              40 :     if (nBands == 0)
     797                 :     {
     798                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     799               2 :                   "XYZ driver does not support source dataset with zero band.\n");
     800               2 :         return NULL;
     801                 :     }
     802                 : 
     803              38 :     if (nBands != 1)
     804                 :     {
     805                 :         CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
     806               8 :                   "XYZ driver only uses the first band of the dataset.\n");
     807               8 :         if (bStrict)
     808               8 :             return NULL;
     809                 :     }
     810                 : 
     811              30 :     if( pfnProgress && !pfnProgress( 0.0, NULL, pProgressData ) )
     812               0 :         return NULL;
     813                 : 
     814                 : /* -------------------------------------------------------------------- */
     815                 : /*      Get source dataset info                                         */
     816                 : /* -------------------------------------------------------------------- */
     817                 : 
     818              30 :     int nXSize = poSrcDS->GetRasterXSize();
     819              30 :     int nYSize = poSrcDS->GetRasterYSize();
     820                 :     double adfGeoTransform[6];
     821              30 :     poSrcDS->GetGeoTransform(adfGeoTransform);
     822              30 :     if (adfGeoTransform[2] != 0 || adfGeoTransform[4] != 0)
     823                 :     {
     824                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     825               0 :                   "XYZ driver does not support CreateCopy() from skewed or rotated dataset.\n");
     826               0 :         return NULL;
     827                 :     }
     828                 : 
     829              30 :     GDALDataType eSrcDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();
     830                 :     GDALDataType eReqDT;
     831              44 :     if (eSrcDT == GDT_Byte || eSrcDT == GDT_Int16 ||
     832                 :         eSrcDT == GDT_UInt16 || eSrcDT == GDT_Int32)
     833              14 :         eReqDT = GDT_Int32;
     834                 :     else
     835              16 :         eReqDT = GDT_Float32;
     836                 : 
     837                 : /* -------------------------------------------------------------------- */
     838                 : /*      Create target file                                              */
     839                 : /* -------------------------------------------------------------------- */
     840                 : 
     841              30 :     VSILFILE* fp = VSIFOpenL(pszFilename, "wb");
     842              30 :     if (fp == NULL)
     843                 :     {
     844                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     845               4 :                   "Cannot create %s", pszFilename );
     846               4 :         return NULL;
     847                 :     }
     848                 : 
     849                 : /* -------------------------------------------------------------------- */
     850                 : /*      Read creation options                                           */
     851                 : /* -------------------------------------------------------------------- */
     852                 :     const char* pszColSep =
     853              26 :             CSLFetchNameValue(papszOptions, "COLUMN_SEPARATOR");
     854              26 :     if (pszColSep == NULL)
     855              24 :         pszColSep = " ";
     856               2 :     else if (EQUAL(pszColSep, "COMMA"))
     857               0 :         pszColSep = ",";
     858               2 :     else if (EQUAL(pszColSep, "SPACE"))
     859               0 :         pszColSep = " ";
     860               2 :     else if (EQUAL(pszColSep, "SEMICOLON"))
     861               0 :         pszColSep = ";";
     862               2 :     else if (EQUAL(pszColSep, "\\t") || EQUAL(pszColSep, "TAB"))
     863               0 :         pszColSep = "\t";
     864                 : 
     865                 :     const char* pszAddHeaderLine =
     866              26 :             CSLFetchNameValue(papszOptions, "ADD_HEADER_LINE");
     867              26 :     if (pszAddHeaderLine != NULL && CSLTestBoolean(pszAddHeaderLine))
     868                 :     {
     869               2 :         VSIFPrintfL(fp, "X%sY%sZ\n", pszColSep, pszColSep);
     870                 :     }
     871                 : 
     872                 : /* -------------------------------------------------------------------- */
     873                 : /*      Copy imagery                                                    */
     874                 : /* -------------------------------------------------------------------- */
     875              26 :     void* pLineBuffer = (void*) CPLMalloc(nXSize * sizeof(int));
     876                 :     int i, j;
     877              26 :     CPLErr eErr = CE_None;
     878              26 :     for(j=0;j<nYSize && eErr == CE_None;j++)
     879                 :     {
     880                 :         eErr = poSrcDS->GetRasterBand(1)->RasterIO(
     881                 :                                             GF_Read, 0, j, nXSize, 1,
     882                 :                                             pLineBuffer, nXSize, 1,
     883             662 :                                             eReqDT, 0, 0);
     884             662 :         if (eErr != CE_None)
     885               0 :             break;
     886             662 :         double dfY = adfGeoTransform[3] + (j + 0.5) * adfGeoTransform[5];
     887             662 :         CPLString osBuf;
     888           84464 :         for(i=0;i<nXSize;i++)
     889                 :         {
     890                 :             char szBuf[256];
     891           83802 :             double dfX = adfGeoTransform[0] + (i + 0.5) * adfGeoTransform[1];
     892           83802 :             if (eReqDT == GDT_Int32)
     893            1600 :                 sprintf(szBuf, "%.18g%c%.18g%c%d\n", dfX, pszColSep[0], dfY, pszColSep[0], ((int*)pLineBuffer)[i]);
     894                 :             else
     895           82202 :                 sprintf(szBuf, "%.18g%c%.18g%c%.18g\n", dfX, pszColSep[0], dfY, pszColSep[0], ((float*)pLineBuffer)[i]);
     896           83802 :             osBuf += szBuf;
     897           83802 :             if( (i & 1023) == 0 || i == nXSize - 1 )
     898                 :             {
     899            1324 :                 if ( VSIFWriteL( osBuf, (int)osBuf.size(), 1, fp ) != 1 )
     900                 :                 {
     901               0 :                     eErr = CE_Failure;
     902                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     903               0 :                               "Write failed, disk full?\n" );
     904               0 :                     break;
     905                 :                 }
     906            1324 :                 osBuf = "";
     907                 :             }
     908                 :         }
     909             662 :         if (!pfnProgress( (j+1) * 1.0 / nYSize, NULL, pProgressData))
     910                 :             break;
     911                 :     }
     912              26 :     CPLFree(pLineBuffer);
     913              26 :     VSIFCloseL(fp);
     914                 :     
     915              26 :     if (eErr != CE_None)
     916               0 :         return NULL;
     917                 : 
     918                 :     /* If outputing to stdout, we can't reopen it, so we'll return */
     919                 :     /* a fake dataset to make the caller happy */
     920              26 :     CPLPushErrorHandler(CPLQuietErrorHandler);
     921              26 :     GDALDataset* poDS = (GDALDataset*) GDALOpen(pszFilename, GA_ReadOnly);
     922              26 :     CPLPopErrorHandler();
     923              26 :     if (poDS)
     924              26 :         return poDS;
     925                 : 
     926               0 :     CPLErrorReset();
     927                 : 
     928               0 :     XYZDataset* poXYZ_DS = new XYZDataset();
     929               0 :     poXYZ_DS->nRasterXSize = nXSize;
     930               0 :     poXYZ_DS->nRasterYSize = nYSize;
     931               0 :     poXYZ_DS->nBands = 1;
     932               0 :     poXYZ_DS->SetBand( 1, new XYZRasterBand( poXYZ_DS, 1, eReqDT ) );
     933               0 :     return poXYZ_DS;
     934                 : }
     935                 : 
     936                 : /************************************************************************/
     937                 : /*                          GetGeoTransform()                           */
     938                 : /************************************************************************/
     939                 : 
     940               2 : CPLErr XYZDataset::GetGeoTransform( double * padfTransform )
     941                 : 
     942                 : {
     943               2 :     memcpy(padfTransform, adfGeoTransform, 6 * sizeof(double));
     944                 : 
     945               2 :     return( CE_None );
     946                 : }
     947                 : 
     948                 : /************************************************************************/
     949                 : /*                         GDALRegister_XYZ()                           */
     950                 : /************************************************************************/
     951                 : 
     952            1135 : void GDALRegister_XYZ()
     953                 : 
     954                 : {
     955                 :     GDALDriver  *poDriver;
     956                 : 
     957            1135 :     if( GDALGetDriverByName( "XYZ" ) == NULL )
     958                 :     {
     959            1093 :         poDriver = new GDALDriver();
     960                 :         
     961            1093 :         poDriver->SetDescription( "XYZ" );
     962                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
     963            1093 :                                    "ASCII Gridded XYZ" );
     964                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
     965            1093 :                                    "frmt_xyz.html" );
     966            1093 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "xyz" );
     967                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
     968                 : "<CreationOptionList>"
     969                 : "   <Option name='COLUMN_SEPARATOR' type='string' default=' ' description='Separator between fields.'/>"
     970                 : "   <Option name='ADD_HEADER_LINE' type='boolean' default='false' description='Add an header line with column names.'/>"
     971            1093 : "</CreationOptionList>");
     972                 : 
     973            1093 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
     974                 : 
     975            1093 :         poDriver->pfnOpen = XYZDataset::Open;
     976            1093 :         poDriver->pfnIdentify = XYZDataset::Identify;
     977            1093 :         poDriver->pfnCreateCopy = XYZDataset::CreateCopy;
     978                 : 
     979            1093 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     980                 :     }
     981            1135 : }
     982                 : 

Generated by: LCOV version 1.7