int OGRCSVDataSource::OpenTable( const char * pszFilename, const char* pszNfdcRunwaysGeomField, const char* pszGeonamesGeomFieldPrefix) { /* -------------------------------------------------------------------- */ /* Open the file. */ /* -------------------------------------------------------------------- */ VSILFILE * fp; if( bUpdate ) fp = VSIFOpenL( pszFilename, "rb+" ); else fp = VSIFOpenL( pszFilename, "rb" ); if( fp == NULL ) { CPLError( CE_Warning, CPLE_OpenFailed, "Failed to open %s, %s.", pszFilename, VSIStrerror( errno ) ); return FALSE; } if( !bUpdate && strstr(pszFilename, "/vsigzip/") == NULL && strstr(pszFilename, "/vsizip/") == NULL ) fp = (VSILFILE*) VSICreateBufferedReaderHandle((VSIVirtualHandle*)fp); CPLString osLayerName = CPLGetBasename(pszFilename); CPLString osExt = CPLGetExtension(pszFilename); if( strncmp(pszFilename, "/vsigzip/", 9) == 0 && EQUAL(osExt, "gz") ) { if( strlen(pszFilename) > 7 && EQUAL(pszFilename + strlen(pszFilename) - 7, ".csv.gz") ) { osLayerName = osLayerName.substr(0, osLayerName.size() - 4); osExt = "csv"; } else if( strlen(pszFilename) > 7 && EQUAL(pszFilename + strlen(pszFilename) - 7, ".tsv.gz") ) { osLayerName = osLayerName.substr(0, osLayerName.size() - 4); osExt = "tsv"; } } /* -------------------------------------------------------------------- */ /* Read and parse a line. Did we get multiple fields? */ /* -------------------------------------------------------------------- */ const char* pszLine = CPLReadLineL( fp ); if (pszLine == NULL) { VSIFCloseL( fp ); return FALSE; } char chDelimiter = CSVDetectSeperator(pszLine); /* Force the delimiter to be TAB for a .tsv file that has a tabulation */ /* in its first line */ if( EQUAL(osExt, "tsv") && chDelimiter != '\t' && strchr(pszLine, '\t') != NULL ) { chDelimiter = '\t'; } VSIRewindL( fp ); /* GNIS specific */ if (pszGeonamesGeomFieldPrefix != NULL && strchr(pszLine, '|') != NULL) chDelimiter = '|'; char **papszFields = OGRCSVReadParseLineL( fp, chDelimiter, FALSE ); if( CSLCount(papszFields) < 2 ) { VSIFCloseL( fp ); CSLDestroy( papszFields ); return FALSE; } VSIRewindL( fp ); CSLDestroy( papszFields ); /* -------------------------------------------------------------------- */ /* Create a layer. */ /* -------------------------------------------------------------------- */ nLayers++; papoLayers = (OGRCSVLayer **) CPLRealloc(papoLayers, sizeof(void*) * nLayers); if (pszNfdcRunwaysGeomField != NULL) { osLayerName += "_"; osLayerName += pszNfdcRunwaysGeomField; } else if (pszGeonamesGeomFieldPrefix != NULL && !EQUAL(pszGeonamesGeomFieldPrefix, "")) { osLayerName += "_"; osLayerName += pszGeonamesGeomFieldPrefix; } if (EQUAL(pszFilename, "/vsistdin/")) osLayerName = "layer"; papoLayers[nLayers-1] = new OGRCSVLayer( osLayerName, fp, pszFilename, FALSE, bUpdate, chDelimiter, pszNfdcRunwaysGeomField, pszGeonamesGeomFieldPrefix ); return TRUE; }
int OGRCSVDataSource::OpenTable( const char * pszFilename, char** papszOpenOptions, const char* pszNfdcRunwaysGeomField, const char* pszGeonamesGeomFieldPrefix) { /* -------------------------------------------------------------------- */ /* Open the file. */ /* -------------------------------------------------------------------- */ VSILFILE * fp; if( bUpdate ) fp = VSIFOpenL( pszFilename, "rb+" ); else fp = VSIFOpenL( pszFilename, "rb" ); if( fp == NULL ) { CPLError( CE_Warning, CPLE_OpenFailed, "Failed to open %s, %s.", pszFilename, VSIStrerror( errno ) ); return FALSE; } if( !bUpdate && strstr(pszFilename, "/vsigzip/") == NULL && strstr(pszFilename, "/vsizip/") == NULL ) fp = (VSILFILE*) VSICreateBufferedReaderHandle((VSIVirtualHandle*)fp); CPLString osLayerName = CPLGetBasename(pszFilename); CPLString osExt = CPLGetExtension(pszFilename); if( strncmp(pszFilename, "/vsigzip/", 9) == 0 && EQUAL(osExt, "gz") ) { if( strlen(pszFilename) > 7 && EQUAL(pszFilename + strlen(pszFilename) - 7, ".csv.gz") ) { osLayerName = osLayerName.substr(0, osLayerName.size() - 4); osExt = "csv"; } else if( strlen(pszFilename) > 7 && EQUAL(pszFilename + strlen(pszFilename) - 7, ".tsv.gz") ) { osLayerName = osLayerName.substr(0, osLayerName.size() - 4); osExt = "tsv"; } } /* -------------------------------------------------------------------- */ /* Read and parse a line. Did we get multiple fields? */ /* -------------------------------------------------------------------- */ const char* pszLine = CPLReadLineL( fp ); if (pszLine == NULL) { VSIFCloseL( fp ); return FALSE; } char chDelimiter = CSVDetectSeperator(pszLine); if( chDelimiter != '\t' && strchr(pszLine, '\t') != NULL ) { /* Force the delimiter to be TAB for a .tsv file that has a tabulation */ /* in its first line */ if( EQUAL(osExt, "tsv") ) { chDelimiter = '\t'; } else { for(int bDontHonourStrings=0; bDontHonourStrings<=1; bDontHonourStrings++) { // Read the first 2 lines to see if they have the same number of fields, if using tabulation VSIRewindL( fp ); char** papszTokens = OGRCSVReadParseLineL( fp, '\t', bDontHonourStrings ); int nTokens1 = CSLCount(papszTokens); CSLDestroy(papszTokens); papszTokens = OGRCSVReadParseLineL( fp, '\t', bDontHonourStrings ); int nTokens2 = CSLCount(papszTokens); CSLDestroy(papszTokens); if( nTokens1 >= 2 && nTokens1 == nTokens2 ) { chDelimiter = '\t'; break; } } } } VSIRewindL( fp ); #if 0 const char *pszDelimiter = CSLFetchNameValueDef( papszOpenOptions, "SEPARATOR", "AUTO"); if( !EQUAL(pszDelimiter, "AUTO") ) { if (EQUAL(pszDelimiter, "COMMA")) chDelimiter = ','; else if (EQUAL(pszDelimiter, "SEMICOLON")) chDelimiter = ';'; else if (EQUAL(pszDelimiter, "TAB")) chDelimiter = '\t'; else if (EQUAL(pszDelimiter, "SPACE")) chDelimiter = ' '; else { CPLError( CE_Warning, CPLE_AppDefined, "SEPARATOR=%s not understood, use one of COMMA, SEMICOLON, SPACE or TAB.", pszDelimiter ); } } #endif /* GNIS specific */ if (pszGeonamesGeomFieldPrefix != NULL && strchr(pszLine, '|') != NULL) chDelimiter = '|'; char **papszFields = OGRCSVReadParseLineL( fp, chDelimiter, FALSE ); if( CSLCount(papszFields) < 2 ) { VSIFCloseL( fp ); CSLDestroy( papszFields ); return FALSE; } VSIRewindL( fp ); CSLDestroy( papszFields ); /* -------------------------------------------------------------------- */ /* Create a layer. */ /* -------------------------------------------------------------------- */ nLayers++; papoLayers = (OGRCSVLayer **) CPLRealloc(papoLayers, sizeof(void*) * nLayers); if (pszNfdcRunwaysGeomField != NULL) { osLayerName += "_"; osLayerName += pszNfdcRunwaysGeomField; } else if (pszGeonamesGeomFieldPrefix != NULL && !EQUAL(pszGeonamesGeomFieldPrefix, "")) { osLayerName += "_"; osLayerName += pszGeonamesGeomFieldPrefix; } if (EQUAL(pszFilename, "/vsistdin/")) osLayerName = "layer"; papoLayers[nLayers-1] = new OGRCSVLayer( osLayerName, fp, pszFilename, FALSE, bUpdate, chDelimiter ); papoLayers[nLayers-1]->BuildFeatureDefn( pszNfdcRunwaysGeomField, pszGeonamesGeomFieldPrefix, papszOpenOptions ); return TRUE; }
int OGRSelafinDataSource::OpenTable(const char * pszFilename) { //CPLDebug("Selafin","OpenTable(%s,%i)",pszFilename,bUpdate); // Open the file VSILFILE * fp; if( bUpdate ) { // We have to implement this locking feature for write access because the same file may hold several layers, and some programs (like QGIS) open each layer in a single datasource, // so the same file might be opened several times for write access if (TakeLock(pszFilename)==0) { CPLError(CE_Failure,CPLE_OpenFailed,"Failed to open %s for write access, lock file found %s.",pszFilename,pszLockName); return FALSE; } fp = VSIFOpenL( pszFilename, "rb+" ); } else fp = VSIFOpenL( pszFilename, "rb" ); if( fp == NULL ) { CPLError( CE_Warning, CPLE_OpenFailed, "Failed to open %s, %s.", pszFilename, VSIStrerror( errno ) ); return FALSE; } if( !bUpdate && strstr(pszFilename, "/vsigzip/") == NULL && strstr(pszFilename, "/vsizip/") == NULL ) fp = (VSILFILE*) VSICreateBufferedReaderHandle((VSIVirtualHandle*)fp); // Quickly check if the file is in Selafin format, before actually starting to read to make it faster char szBuf[9]; VSIFReadL(szBuf,1,4,fp); if (szBuf[0]!=0 || szBuf[1]!=0 || szBuf[2]!=0 || szBuf[3]!=0x50) { VSIFCloseL(fp); return FALSE; } VSIFSeekL(fp,84,SEEK_SET); VSIFReadL(szBuf,1,8,fp); if (szBuf[0]!=0 || szBuf[1]!=0 || szBuf[2]!=0 || szBuf[3]!=0x50 || szBuf[4]!=0 || szBuf[5]!=0 || szBuf[6]!=0 || szBuf[7]!=8) { VSIFCloseL(fp); return FALSE; } /* VSIFSeekL(fp,76,SEEK_SET); VSIFReadL(szBuf,1,8,fp); if (STRNCASECMP(szBuf,"Seraphin",8)!=0 && STRNCASECMP(szBuf,"Serafin",7)!=0) { VSIFCloseL(fp); return FALSE; } */ // Get layer base name CPLString osBaseLayerName = CPLGetBasename(pszFilename); CPLString osExt = CPLGetExtension(pszFilename); if( STARTS_WITH(pszFilename, "/vsigzip/") && EQUAL(osExt, "gz") ) { size_t nPos=std::string::npos; if (strlen(pszFilename)>3) nPos=osExt.find_last_of('.',strlen(pszFilename)-4); if (nPos!=std::string::npos) { osExt=osExt.substr(nPos+1,strlen(pszFilename)-4-nPos); osBaseLayerName=osBaseLayerName.substr(0,nPos); } else { osExt=""; } } // Read header of file to get common information for all layers poHeader=Selafin::read_header(fp,pszFilename); if (poHeader==NULL) { VSIFCloseL(fp); CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open %s, wrong format.\n", pszFilename); return FALSE; } if (poHeader->nEpsg!=0) { poSpatialRef=new OGRSpatialReference(); if (poSpatialRef->importFromEPSG(poHeader->nEpsg)!=OGRERR_NONE) { CPLError( CE_Warning, CPLE_AppDefined, "EPSG %d not found. Could not set datasource SRS.\n", poHeader->nEpsg); delete poSpatialRef; poSpatialRef=NULL; } } // Create two layers for each selected time step: one for points, the other for elements int nNewLayers; poRange.setMaxValue(poHeader->nSteps); nNewLayers=static_cast<int>(poRange.getSize()); if (EQUAL(pszFilename, "/vsistdin/")) osBaseLayerName = "layer"; CPLString osLayerName; papoLayers = (OGRSelafinLayer **) CPLRealloc(papoLayers, sizeof(void*) * (nLayers+nNewLayers)); for (size_t j=0;j<2;++j) { SelafinTypeDef eType=(j==0)?POINTS:ELEMENTS; for (int i=0;i<poHeader->nSteps;++i) { if (poRange.contains(eType,i)) { char szTemp[30]; double dfTime; if (VSIFSeekL(fp,poHeader->getPosition(i)+4,SEEK_SET)!=0 || Selafin::read_float(fp,dfTime)==0) { VSIFCloseL(fp); CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open %s, wrong format.\n", pszFilename); return FALSE; } if (poHeader->panStartDate==NULL) snprintf(szTemp,29,"%d",i); else { struct tm sDate; memset(&sDate, 0, sizeof(sDate)); sDate.tm_year=poHeader->panStartDate[0]-1900; sDate.tm_mon=poHeader->panStartDate[1]-1; sDate.tm_mday=poHeader->panStartDate[2]; sDate.tm_hour=poHeader->panStartDate[3]; sDate.tm_min=poHeader->panStartDate[4]; sDate.tm_sec=poHeader->panStartDate[5]+(int)dfTime; mktime(&sDate); strftime(szTemp,29,"%Y_%m_%d_%H_%M_%S",&sDate); } if (eType==POINTS) osLayerName=osBaseLayerName+"_p"+szTemp; else osLayerName=osBaseLayerName+"_e"+szTemp; papoLayers[nLayers++] = new OGRSelafinLayer( osLayerName, bUpdate, poSpatialRef, poHeader,i,eType); //poHeader->nRefCount++; } } } // Free allocated variables and exit return TRUE; }
int OGRSelafinDataSource::OpenTable(const char * pszFilename) { #ifdef DEBUG_VERBOSE CPLDebug("Selafin", "OpenTable(%s,%i)", pszFilename, static_cast<int>(bUpdate)); #endif // Open the file VSILFILE *fp = nullptr; if( bUpdate ) { fp = VSIFOpenExL( pszFilename, "rb+", true ); } else { fp = VSIFOpenExL( pszFilename, "rb", true ); } if( fp == nullptr ) { CPLError( CE_Warning, CPLE_OpenFailed, "Failed to open %s.", VSIGetLastErrorMsg() ); return FALSE; } if( !bUpdate && strstr(pszFilename, "/vsigzip/") == nullptr && strstr(pszFilename, "/vsizip/") == nullptr ) fp = (VSILFILE*) VSICreateBufferedReaderHandle((VSIVirtualHandle*)fp); // Quickly check if the file is in Selafin format, before actually starting to read to make it faster char szBuf[9]; VSIFReadL(szBuf,1,4,fp); if (szBuf[0]!=0 || szBuf[1]!=0 || szBuf[2]!=0 || szBuf[3]!=0x50) { VSIFCloseL(fp); return FALSE; } VSIFSeekL(fp,84,SEEK_SET); VSIFReadL(szBuf,1,8,fp); if (szBuf[0]!=0 || szBuf[1]!=0 || szBuf[2]!=0 || szBuf[3]!=0x50 || szBuf[4]!=0 || szBuf[5]!=0 || szBuf[6]!=0 || szBuf[7]!=8) { VSIFCloseL(fp); return FALSE; } /* VSIFSeekL(fp,76,SEEK_SET); VSIFReadL(szBuf,1,8,fp); if (STRNCASECMP(szBuf,"Seraphin",8)!=0 && STRNCASECMP(szBuf,"Serafin",7)!=0) { VSIFCloseL(fp); return FALSE; } */ // Get layer base name CPLString osBaseLayerName = CPLGetBasename(pszFilename); CPLString osExt = CPLGetExtension(pszFilename); if( STARTS_WITH(pszFilename, "/vsigzip/") && EQUAL(osExt, "gz") ) { size_t nPos=std::string::npos; if (strlen(pszFilename)>3) nPos=osExt.find_last_of('.',strlen(pszFilename)-4); if (nPos!=std::string::npos) { osExt=osExt.substr(nPos+1,strlen(pszFilename)-4-nPos); osBaseLayerName=osBaseLayerName.substr(0,nPos); } else { osExt=""; } } // Read header of file to get common information for all layers // poHeader now owns fp poHeader=Selafin::read_header(fp,pszFilename); if (poHeader==nullptr) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open %s, wrong format.\n", pszFilename); return FALSE; } if (poHeader->nEpsg!=0) { poSpatialRef=new OGRSpatialReference(); poSpatialRef->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); if (poSpatialRef->importFromEPSG(poHeader->nEpsg)!=OGRERR_NONE) { CPLError( CE_Warning, CPLE_AppDefined, "EPSG %d not found. Could not set datasource SRS.\n", poHeader->nEpsg); delete poSpatialRef; poSpatialRef=nullptr; } } // To prevent int overflow in poRange.getSize() call where we do // nSteps * 2 if( poHeader->nSteps >= INT_MAX / 2 ) { CPLError( CE_Failure, CPLE_OpenFailed, "Invalid nSteps value" ); return FALSE; } // Create two layers for each selected time step: one for points, the other for elements poRange.setMaxValue(poHeader->nSteps); const int nNewLayers = static_cast<int>(poRange.getSize()); if (EQUAL(pszFilename, "/vsistdin/")) osBaseLayerName = "layer"; CPLString osLayerName; papoLayers = (OGRSelafinLayer **) CPLRealloc(papoLayers, sizeof(void*) * (nLayers+nNewLayers)); for (size_t j=0;j<2;++j) { SelafinTypeDef eType=(j==0)?POINTS:ELEMENTS; for (int i=0;i<poHeader->nSteps;++i) { if (poRange.contains(eType,i)) { char szTemp[30]; double dfTime = 0.0; if( VSIFSeekL(fp, poHeader->getPosition(i)+4, SEEK_SET)!=0 || Selafin::read_float(fp, dfTime)==0 ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open %s, wrong format.\n", pszFilename); return FALSE; } if (poHeader->panStartDate==nullptr) snprintf(szTemp,29,"%d",i); else { struct tm sDate; memset(&sDate, 0, sizeof(sDate)); sDate.tm_year=poHeader->panStartDate[0]-1900; sDate.tm_mon=poHeader->panStartDate[1]-1; sDate.tm_mday=poHeader->panStartDate[2]; sDate.tm_hour=poHeader->panStartDate[3]; sDate.tm_min=poHeader->panStartDate[4]; double dfSec=poHeader->panStartDate[5]+dfTime; if( dfSec >= 0 && dfSec < 60 ) sDate.tm_sec=static_cast<int>(dfSec); mktime(&sDate); strftime(szTemp,29,"%Y_%m_%d_%H_%M_%S",&sDate); } if (eType==POINTS) osLayerName=osBaseLayerName+"_p"+szTemp; else osLayerName=osBaseLayerName+"_e"+szTemp; papoLayers[nLayers++] = new OGRSelafinLayer( osLayerName, bUpdate, poSpatialRef, poHeader, i, eType); //poHeader->nRefCount++; } } } // Free allocated variables and exit return TRUE; }
GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo ) { int i; int bHasHeaderLine; int nCommentLineCount = 0; if (!IdentifyEx(poOpenInfo, bHasHeaderLine, nCommentLineCount)) return NULL; CPLString osFilename(poOpenInfo->pszFilename); /* GZipped .xyz files are common, so automagically open them */ /* if the /vsigzip/ has not been explicitly passed */ if (strlen(poOpenInfo->pszFilename) > 6 && EQUAL(poOpenInfo->pszFilename + strlen(poOpenInfo->pszFilename) - 6, "xyz.gz") && !EQUALN(poOpenInfo->pszFilename, "/vsigzip/", 9)) { osFilename = "/vsigzip/"; osFilename += poOpenInfo->pszFilename; } /* -------------------------------------------------------------------- */ /* Find dataset characteristics */ /* -------------------------------------------------------------------- */ VSILFILE* fp = VSIFOpenL(osFilename.c_str(), "rb"); if (fp == NULL) return NULL; /* For better performance of CPLReadLine2L() we create a buffered reader */ /* (except for /vsigzip/ since it has one internally) */ if (!EQUALN(poOpenInfo->pszFilename, "/vsigzip/", 9)) fp = (VSILFILE*) VSICreateBufferedReaderHandle((VSIVirtualHandle*)fp); const char* pszLine; int nXIndex = -1, nYIndex = -1, nZIndex = -1; int nMinTokens = 0; for(i=0;i<nCommentLineCount;i++) CPLReadLine2L(fp, 100, NULL); /* -------------------------------------------------------------------- */ /* Parse header line */ /* -------------------------------------------------------------------- */ if (bHasHeaderLine) { pszLine = CPLReadLine2L(fp, 100, NULL); if (pszLine == NULL) { VSIFCloseL(fp); return NULL; } char** papszTokens = CSLTokenizeString2( pszLine, " ,\t;", CSLT_HONOURSTRINGS ); int nTokens = CSLCount(papszTokens); if (nTokens < 3) { CPLError(CE_Failure, CPLE_AppDefined, "At line %d, found %d tokens. Expected 3 at least", 1, nTokens); CSLDestroy(papszTokens); VSIFCloseL(fp); return NULL; } int i; for(i=0;i<nTokens;i++) { if (EQUAL(papszTokens[i], "x") || EQUALN(papszTokens[i], "lon", 3) || EQUALN(papszTokens[i], "east", 4)) nXIndex = i; else if (EQUAL(papszTokens[i], "y") || EQUALN(papszTokens[i], "lat", 3) || EQUALN(papszTokens[i], "north", 5)) nYIndex = i; else if (EQUAL(papszTokens[i], "z") || EQUALN(papszTokens[i], "alt", 3) || EQUAL(papszTokens[i], "height")) nZIndex = i; } CSLDestroy(papszTokens); papszTokens = NULL; if (nXIndex < 0 || nYIndex < 0 || nZIndex < 0) { CPLError(CE_Warning, CPLE_AppDefined, "Could not find one of the X, Y or Z column names in header line. Defaulting to the first 3 columns"); nXIndex = 0; nYIndex = 1; nZIndex = 2; } nMinTokens = 1 + MAX(MAX(nXIndex, nYIndex), nZIndex); } else { nXIndex = 0; nYIndex = 1; nZIndex = 2; nMinTokens = 3; } /* -------------------------------------------------------------------- */ /* Parse data lines */ /* -------------------------------------------------------------------- */ int nLineNum = 0; int nDataLineNum = 0; double dfX = 0, dfY = 0, dfZ = 0; double dfMinX = 0, dfMinY = 0, dfMaxX = 0, dfMaxY = 0; double dfMinZ = 0, dfMaxZ = 0; double dfLastX = 0, dfLastY = 0; std::vector<double> adfStepX, adfStepY; GDALDataType eDT = GDT_Byte; int bSameNumberOfValuesPerLine = TRUE; char chDecimalSep = '\0'; int bStepYSign = 0; while((pszLine = CPLReadLine2L(fp, 100, NULL)) != NULL) { nLineNum ++; const char* pszPtr = pszLine; char ch; int nCol = 0; int bLastWasSep = TRUE; if( chDecimalSep == '\0' ) { int nCountComma = 0; int nCountFieldSep = 0; while((ch = *pszPtr) != '\0') { if( ch == '.' ) { chDecimalSep = '.'; break; } else if( ch == ',' ) { nCountComma ++; bLastWasSep = FALSE; } else if( ch == ' ' ) { if (!bLastWasSep) nCountFieldSep ++; bLastWasSep = TRUE; } else if( ch == '\t' || ch == ';' ) { nCountFieldSep ++; bLastWasSep = TRUE; } else bLastWasSep = FALSE; pszPtr ++; } if( chDecimalSep == '\0' ) { /* 1,2,3 */ if( nCountComma >= 2 && nCountFieldSep == 0 ) chDecimalSep = '.'; /* 23,5;33;45 */ else if ( nCountComma > 0 && nCountFieldSep > 0 ) chDecimalSep = ','; } pszPtr = pszLine; bLastWasSep = TRUE; } char chLocalDecimalSep = chDecimalSep ? chDecimalSep : '.'; while((ch = *pszPtr) != '\0') { if (ch == ' ') { if (!bLastWasSep) nCol ++; bLastWasSep = TRUE; } else if ((ch == ',' && chLocalDecimalSep != ',') || ch == '\t' || ch == ';') { nCol ++; bLastWasSep = TRUE; } else { if (bLastWasSep) { if (nCol == nXIndex) dfX = CPLAtofDelim(pszPtr, chLocalDecimalSep); else if (nCol == nYIndex) dfY = CPLAtofDelim(pszPtr, chLocalDecimalSep); else if (nCol == nZIndex) { dfZ = CPLAtofDelim(pszPtr, chLocalDecimalSep); if( nDataLineNum == 0 ) dfMinZ = dfMaxZ = dfZ; else if( dfZ < dfMinZ ) dfMinZ = dfZ; else if( dfZ > dfMaxZ ) dfMaxZ = dfZ; int nZ = (int)dfZ; if ((double)nZ != dfZ) { eDT = GDT_Float32; } else if ((eDT == GDT_Byte || eDT == GDT_Int16) && (nZ < 0 || nZ > 255)) { if (nZ < -32768 || nZ > 32767) eDT = GDT_Int32; else eDT = GDT_Int16; } } } bLastWasSep = FALSE; } pszPtr ++; } /* skip empty lines */ if (bLastWasSep && nCol == 0) { continue; } nDataLineNum ++; nCol ++; if (nCol < nMinTokens) { CPLError(CE_Failure, CPLE_AppDefined, "At line %d, found %d tokens. Expected %d at least", nLineNum, nCol, nMinTokens); VSIFCloseL(fp); return NULL; } if (nDataLineNum == 1) { dfMinX = dfMaxX = dfX; dfMinY = dfMaxY = dfY; } else { double dfStepY = dfY - dfLastY; if( dfStepY == 0.0 ) { double dfStepX = dfX - dfLastX; if( dfStepX <= 0 ) { CPLError(CE_Failure, CPLE_AppDefined, "Ungridded dataset: At line %d, X spacing was %f. Expected >0 value", nLineNum, dfStepX); VSIFCloseL(fp); return NULL; } if( std::find(adfStepX.begin(), adfStepX.end(), dfStepX) == adfStepX.end() ) { int bAddNewValue = TRUE; std::vector<double>::iterator oIter = adfStepX.begin(); while( oIter != adfStepX.end() ) { if( dfStepX < *oIter && fmod( *oIter, dfStepX ) < 1e-8 ) { adfStepX.erase(oIter); } else if( dfStepX > *oIter && fmod( dfStepX, *oIter ) < 1e-8 ) { bAddNewValue = FALSE; break; } else { ++ oIter; } } if( bAddNewValue ) { adfStepX.push_back(dfStepX); if( adfStepX.size() == 10 ) { CPLError(CE_Failure, CPLE_AppDefined, "Ungridded dataset: too many stepX values"); VSIFCloseL(fp); return NULL; } } } } else { int bNewStepYSign = (dfStepY < 0.0) ? -1 : 1; if( bStepYSign == 0 ) bStepYSign = bNewStepYSign; else if( bStepYSign != bNewStepYSign ) { CPLError(CE_Failure, CPLE_AppDefined, "Ungridded dataset: At line %d, change of Y direction", nLineNum); VSIFCloseL(fp); return NULL; } if( bNewStepYSign < 0 ) dfStepY = -dfStepY; if( adfStepY.size() == 0 ) adfStepY.push_back(dfStepY); else if( adfStepY[0] != dfStepY ) { CPLError(CE_Failure, CPLE_AppDefined, "Ungridded dataset: At line %d, too many stepY values", nLineNum); VSIFCloseL(fp); return NULL; } } if (dfX < dfMinX) dfMinX = dfX; if (dfX > dfMaxX) dfMaxX = dfX; if (dfY < dfMinY) dfMinY = dfY; if (dfY > dfMaxY) dfMaxY = dfY; } dfLastX = dfX; dfLastY = dfY; } if (adfStepX.size() != 1) { CPLError(CE_Failure, CPLE_AppDefined, "Couldn't determine X spacing"); VSIFCloseL(fp); return NULL; } if (adfStepY.size() != 1) { CPLError(CE_Failure, CPLE_AppDefined, "Couldn't determine Y spacing"); VSIFCloseL(fp); return NULL; } double dfStepX = adfStepX[0]; double dfStepY = adfStepY[0] * bStepYSign; int nXSize = 1 + int((dfMaxX - dfMinX) / dfStepX + 0.5); int nYSize = 1 + int((dfMaxY - dfMinY) / fabs(dfStepY) + 0.5); //CPLDebug("XYZ", "minx=%f maxx=%f stepx=%f", dfMinX, dfMaxX, dfStepX); //CPLDebug("XYZ", "miny=%f maxy=%f stepy=%f", dfMinY, dfMaxY, dfStepY); if (nDataLineNum != nXSize * nYSize) { bSameNumberOfValuesPerLine = FALSE; } if (poOpenInfo->eAccess == GA_Update) { CPLError( CE_Failure, CPLE_NotSupported, "The XYZ driver does not support update access to existing" " datasets.\n" ); VSIFCloseL(fp); return NULL; } /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ XYZDataset *poDS; poDS = new XYZDataset(); poDS->fp = fp; poDS->bHasHeaderLine = bHasHeaderLine; poDS->nCommentLineCount = nCommentLineCount; poDS->chDecimalSep = chDecimalSep ? chDecimalSep : '.'; poDS->nXIndex = nXIndex; poDS->nYIndex = nYIndex; poDS->nZIndex = nZIndex; poDS->nMinTokens = nMinTokens; poDS->nRasterXSize = nXSize; poDS->nRasterYSize = nYSize; poDS->adfGeoTransform[0] = dfMinX - dfStepX / 2; poDS->adfGeoTransform[1] = dfStepX; poDS->adfGeoTransform[3] = (dfStepY < 0) ? dfMaxY - dfStepY / 2 : dfMinY - dfStepY / 2; poDS->adfGeoTransform[5] = dfStepY; poDS->bSameNumberOfValuesPerLine = bSameNumberOfValuesPerLine; poDS->dfMinZ = dfMinZ; poDS->dfMaxZ = dfMaxZ; //CPLDebug("XYZ", "bSameNumberOfValuesPerLine = %d", bSameNumberOfValuesPerLine); if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize)) { delete poDS; return NULL; } /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ poDS->nBands = 1; for( i = 0; i < poDS->nBands; i++ ) poDS->SetBand( i+1, new XYZRasterBand( poDS, i+1, eDT ) ); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Support overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return( poDS ); }
GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo ) { int i; int bHasHeaderLine; int nCommentLineCount = 0; if (!IdentifyEx(poOpenInfo, bHasHeaderLine, nCommentLineCount)) return NULL; CPLString osFilename(poOpenInfo->pszFilename); /* GZipped .xyz files are common, so automagically open them */ /* if the /vsigzip/ has not been explicitely passed */ if (strlen(poOpenInfo->pszFilename) > 6 && EQUAL(poOpenInfo->pszFilename + strlen(poOpenInfo->pszFilename) - 6, "xyz.gz") && !EQUALN(poOpenInfo->pszFilename, "/vsigzip/", 9)) { osFilename = "/vsigzip/"; osFilename += poOpenInfo->pszFilename; } /* -------------------------------------------------------------------- */ /* Find dataset characteristics */ /* -------------------------------------------------------------------- */ VSILFILE* fp = VSIFOpenL(osFilename.c_str(), "rb"); if (fp == NULL) return NULL; /* For better performance of CPLReadLine2L() we create a buffered reader */ /* (except for /vsigzip/ since it has one internally) */ if (!EQUALN(poOpenInfo->pszFilename, "/vsigzip/", 9)) fp = (VSILFILE*) VSICreateBufferedReaderHandle((VSIVirtualHandle*)fp); const char* pszLine; int nXIndex = -1, nYIndex = -1, nZIndex = -1; int nMinTokens = 0; for(i=0;i<nCommentLineCount;i++) CPLReadLine2L(fp, 100, NULL); /* -------------------------------------------------------------------- */ /* Parse header line */ /* -------------------------------------------------------------------- */ if (bHasHeaderLine) { pszLine = CPLReadLine2L(fp, 100, NULL); if (pszLine == NULL) { VSIFCloseL(fp); return NULL; } char** papszTokens = CSLTokenizeString2( pszLine, " ,\t;", CSLT_HONOURSTRINGS ); int nTokens = CSLCount(papszTokens); if (nTokens < 3) { CPLError(CE_Failure, CPLE_AppDefined, "At line %d, found %d tokens. Expected 3 at least", 1, nTokens); CSLDestroy(papszTokens); VSIFCloseL(fp); return NULL; } int i; for(i=0;i<nTokens;i++) { if (EQUAL(papszTokens[i], "x") || EQUALN(papszTokens[i], "lon", 3) || EQUALN(papszTokens[i], "east", 4)) nXIndex = i; else if (EQUAL(papszTokens[i], "y") || EQUALN(papszTokens[i], "lat", 3) || EQUALN(papszTokens[i], "north", 5)) nYIndex = i; else if (EQUAL(papszTokens[i], "z") || EQUALN(papszTokens[i], "alt", 3) || EQUAL(papszTokens[i], "height")) nZIndex = i; } CSLDestroy(papszTokens); papszTokens = NULL; if (nXIndex < 0 || nYIndex < 0 || nZIndex < 0) { CPLError(CE_Warning, CPLE_AppDefined, "Could not find one of the X, Y or Z column names in header line. Defaulting to the first 3 columns"); nXIndex = 0; nYIndex = 1; nZIndex = 2; } nMinTokens = 1 + MAX(MAX(nXIndex, nYIndex), nZIndex); } else { nXIndex = 0; nYIndex = 1; nZIndex = 2; nMinTokens = 3; } /* -------------------------------------------------------------------- */ /* Parse data lines */ /* -------------------------------------------------------------------- */ int nXSize = 0, nYSize = 0; int nLineNum = 0; int nDataLineNum = 0; double dfFirstX = 0; double dfX = 0, dfY = 0, dfZ = 0; double dfMinX = 0, dfMinY = 0, dfMaxX = 0, dfMaxY = 0; double dfLastX = 0, dfLastY = 0; double dfStepX = 0, dfStepY = 0; GDALDataType eDT = GDT_Byte; while((pszLine = CPLReadLine2L(fp, 100, NULL)) != NULL) { nLineNum ++; const char* pszPtr = pszLine; char ch; int nCol = 0; int bLastWasSep = TRUE; while((ch = *pszPtr) != '\0') { if (ch == ' ' || ch == ',' || ch == '\t' || ch == ';') { if (!bLastWasSep) nCol ++; bLastWasSep = TRUE; } else { if (bLastWasSep) { if (nCol == nXIndex) dfX = CPLAtofM(pszPtr); else if (nCol == nYIndex) dfY = CPLAtofM(pszPtr); else if (nCol == nZIndex && eDT != GDT_Float32) { dfZ = CPLAtofM(pszPtr); int nZ = (int)dfZ; if ((double)nZ != dfZ) { eDT = GDT_Float32; } else if ((eDT == GDT_Byte || eDT == GDT_Int16) && (nZ < 0 || nZ > 255)) { if (nZ < -32768 || nZ > 32767) eDT = GDT_Int32; else eDT = GDT_Int16; } } } bLastWasSep = FALSE; } pszPtr ++; } /* skip empty lines */ if (bLastWasSep && nCol == 0) { continue; } nDataLineNum ++; nCol ++; if (nCol < nMinTokens) { CPLError(CE_Failure, CPLE_AppDefined, "At line %d, found %d tokens. Expected %d at least", nLineNum, nCol, nMinTokens); VSIFCloseL(fp); return NULL; } if (nDataLineNum == 1) { dfFirstX = dfMinX = dfMaxX = dfX; dfMinY = dfMaxY = dfY; } else { if (dfX < dfMinX) dfMinX = dfX; if (dfX > dfMaxX) dfMaxX = dfX; if (dfY < dfMinY) dfMinY = dfY; if (dfY > dfMaxY) dfMaxY = dfY; } if (nDataLineNum == 2) { dfStepX = dfX - dfLastX; if (dfStepX <= 0) { CPLError(CE_Failure, CPLE_AppDefined, "Ungridded dataset: At line %d, X spacing was %f. Expected >0 value", nLineNum, dfStepX); VSIFCloseL(fp); return NULL; } } else if (nDataLineNum > 2) { double dfNewStepX = dfX - dfLastX; double dfNewStepY = dfY - dfLastY; if (dfNewStepY != 0) { nYSize ++; if (dfStepY == 0) { nXSize = nDataLineNum - 1; double dfAdjustedStepX = (dfMaxX - dfMinX) / (nXSize - 1); if (fabs(dfStepX - dfAdjustedStepX) > 1e-8) { CPLDebug("XYZ", "Adjusting stepx from %f to %f", dfStepX, dfAdjustedStepX); } dfStepX = dfAdjustedStepX; } if (dfStepY != 0 && fabs(dfX - dfFirstX) > 1e-8) { CPLError(CE_Failure, CPLE_AppDefined, "Ungridded dataset: At line %d, X is %f, where as %f was expected", nLineNum, dfX, dfFirstX); VSIFCloseL(fp); return NULL; } if (dfStepY != 0 && fabs(dfLastX - dfMaxX) > 1e-8) { CPLError(CE_Failure, CPLE_AppDefined, "Ungridded dataset: At line %d, X is %f, where as %f was expected", nLineNum - 1, dfLastX, dfMaxX); VSIFCloseL(fp); return NULL; } /*if (dfStepY != 0 && fabs(dfNewStepY - dfStepY) > 1e-8) { CPLError(CE_Failure, CPLE_AppDefined, "Ungridded dataset: At line %d, Y spacing was %f, whereas it was %f before", nLineNum, dfNewStepY, dfStepY); VSIFCloseL(fp); return NULL; }*/ dfStepY = dfNewStepY; } else if (dfNewStepX != 0) { /*if (dfStepX != 0 && fabs(dfNewStepX - dfStepX) > 1e-8) { CPLError(CE_Failure, CPLE_AppDefined, "At line %d, X spacing was %f, whereas it was %f before", nLineNum, dfNewStepX, dfStepX); VSIFCloseL(fp); return NULL; }*/ } } dfLastX = dfX; dfLastY = dfY; } nYSize ++; if (dfStepX == 0) { CPLError(CE_Failure, CPLE_AppDefined, "Couldn't determine X spacing"); VSIFCloseL(fp); return NULL; } if (dfStepY == 0) { CPLError(CE_Failure, CPLE_AppDefined, "Couldn't determine Y spacing"); VSIFCloseL(fp); return NULL; } double dfAdjustedStepY = ((dfStepY < 0) ? -1 : 1) * (dfMaxY - dfMinY) / (nYSize - 1); if (fabs(dfStepY - dfAdjustedStepY) > 1e-8) { CPLDebug("XYZ", "Adjusting stepy from %f to %f", dfStepY, dfAdjustedStepY); } dfStepY = dfAdjustedStepY; //CPLDebug("XYZ", "minx=%f maxx=%f stepx=%f", dfMinX, dfMaxX, dfStepX); //CPLDebug("XYZ", "miny=%f maxy=%f stepy=%f", dfMinY, dfMaxY, dfStepY); if (nDataLineNum != nXSize * nYSize) { CPLError(CE_Failure, CPLE_AppDefined, "Found %d lines. Expected %d", nDataLineNum,nXSize * nYSize); VSIFCloseL(fp); return NULL; } if (poOpenInfo->eAccess == GA_Update) { CPLError( CE_Failure, CPLE_NotSupported, "The XYZ driver does not support update access to existing" " datasets.\n" ); VSIFCloseL(fp); return NULL; } /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ XYZDataset *poDS; poDS = new XYZDataset(); poDS->fp = fp; poDS->bHasHeaderLine = bHasHeaderLine; poDS->nCommentLineCount = nCommentLineCount; poDS->nXIndex = nXIndex; poDS->nYIndex = nYIndex; poDS->nZIndex = nZIndex; poDS->nMinTokens = nMinTokens; poDS->nRasterXSize = nXSize; poDS->nRasterYSize = nYSize; poDS->adfGeoTransform[0] = dfMinX - dfStepX / 2; poDS->adfGeoTransform[1] = dfStepX; poDS->adfGeoTransform[3] = (dfStepY < 0) ? dfMaxY - dfStepY / 2 : dfMinY - dfStepY / 2; poDS->adfGeoTransform[5] = dfStepY; if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize)) { delete poDS; return NULL; } /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ poDS->nBands = 1; for( i = 0; i < poDS->nBands; i++ ) poDS->SetBand( i+1, new XYZRasterBand( poDS, i+1, eDT ) ); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Support overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return( poDS ); }
GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo ) { int bHasHeaderLine; int nCommentLineCount = 0; if (!IdentifyEx(poOpenInfo, bHasHeaderLine, nCommentLineCount)) return NULL; CPLString osFilename(poOpenInfo->pszFilename); /* GZipped .xyz files are common, so automagically open them */ /* if the /vsigzip/ has not been explicitly passed */ if (strlen(poOpenInfo->pszFilename) > 6 && EQUAL(poOpenInfo->pszFilename + strlen(poOpenInfo->pszFilename) - 6, "xyz.gz") && !STARTS_WITH_CI(poOpenInfo->pszFilename, "/vsigzip/")) { osFilename = "/vsigzip/"; osFilename += poOpenInfo->pszFilename; } /* -------------------------------------------------------------------- */ /* Find dataset characteristics */ /* -------------------------------------------------------------------- */ VSILFILE* fp = VSIFOpenL(osFilename.c_str(), "rb"); if (fp == NULL) return NULL; /* For better performance of CPLReadLine2L() we create a buffered reader */ /* (except for /vsigzip/ since it has one internally) */ if (!STARTS_WITH_CI(poOpenInfo->pszFilename, "/vsigzip/")) fp = reinterpret_cast<VSILFILE *>( VSICreateBufferedReaderHandle( reinterpret_cast<VSIVirtualHandle *>( fp ) ) ); int nXIndex = -1; int nYIndex = -1; int nZIndex = -1; int nMinTokens = 0; for( int i = 0; i < nCommentLineCount; i++ ) { if( CPLReadLine2L(fp, 100, NULL) == NULL ) { VSIFCloseL(fp); return NULL; } } /* -------------------------------------------------------------------- */ /* Parse header line */ /* -------------------------------------------------------------------- */ if (bHasHeaderLine) { const char* pszLine = CPLReadLine2L(fp, 100, NULL); if (pszLine == NULL) { VSIFCloseL(fp); return NULL; } char** papszTokens = CSLTokenizeString2( pszLine, " ,\t;", CSLT_HONOURSTRINGS ); int nTokens = CSLCount(papszTokens); if (nTokens < 3) { CPLError(CE_Failure, CPLE_AppDefined, "At line %d, found %d tokens. Expected 3 at least", 1, nTokens); CSLDestroy(papszTokens); VSIFCloseL(fp); return NULL; } for( int i = 0; i < nTokens; i++ ) { if (EQUAL(papszTokens[i], "x") || STARTS_WITH_CI(papszTokens[i], "lon") || STARTS_WITH_CI(papszTokens[i], "east")) nXIndex = i; else if (EQUAL(papszTokens[i], "y") || STARTS_WITH_CI(papszTokens[i], "lat") || STARTS_WITH_CI(papszTokens[i], "north")) nYIndex = i; else if (EQUAL(papszTokens[i], "z") || STARTS_WITH_CI(papszTokens[i], "alt") || EQUAL(papszTokens[i], "height")) nZIndex = i; } CSLDestroy(papszTokens); papszTokens = NULL; if (nXIndex < 0 || nYIndex < 0 || nZIndex < 0) { CPLError(CE_Warning, CPLE_AppDefined, "Could not find one of the X, Y or Z column names in header line. Defaulting to the first 3 columns"); nXIndex = 0; nYIndex = 1; nZIndex = 2; } nMinTokens = 1 + std::max(std::max(nXIndex, nYIndex), nZIndex); } else { nXIndex = 0; nYIndex = 1; nZIndex = 2; nMinTokens = 3; } /* -------------------------------------------------------------------- */ /* Parse data lines */ /* -------------------------------------------------------------------- */ GIntBig nLineNum = 0; GIntBig nDataLineNum = 0; double dfX = 0.0; double dfY = 0.0; double dfZ = 0.0; double dfMinX = 0.0; double dfMinY = 0.0; double dfMaxX = 0.0; double dfMaxY = 0.0; double dfMinZ = 0.0; double dfMaxZ = 0.0; double dfLastX = 0.0; double dfLastY = 0.0; std::vector<double> adfStepX; std::vector<double> adfStepY; GDALDataType eDT = GDT_Byte; bool bSameNumberOfValuesPerLine = true; char chDecimalSep = '\0'; int bStepYSign = 0; const char* pszLine; GIntBig nCountStepX = 0; GIntBig nCountStepY = 0; while((pszLine = CPLReadLine2L(fp, 100, NULL)) != NULL) { nLineNum ++; const char* pszPtr = pszLine; char ch; int nCol = 0; bool bLastWasSep = true; if( chDecimalSep == '\0' ) { int nCountComma = 0; int nCountFieldSep = 0; while((ch = *pszPtr) != '\0') { if( ch == '.' ) { chDecimalSep = '.'; break; } else if( ch == ',' ) { nCountComma ++; bLastWasSep = false; } else if( ch == ' ' ) { if (!bLastWasSep) nCountFieldSep ++; bLastWasSep = true; } else if( ch == '\t' || ch == ';' ) { nCountFieldSep ++; bLastWasSep = true; } else bLastWasSep = false; pszPtr ++; } if( chDecimalSep == '\0' ) { /* 1,2,3 */ if( nCountComma >= 2 && nCountFieldSep == 0 ) chDecimalSep = '.'; /* 23,5;33;45 */ else if ( nCountComma > 0 && nCountFieldSep > 0 ) chDecimalSep = ','; } pszPtr = pszLine; bLastWasSep = true; } char chLocalDecimalSep = chDecimalSep ? chDecimalSep : '.'; int nUsefulColsFound = 0; while((ch = *pszPtr) != '\0') { if (ch == ' ') { if (!bLastWasSep) nCol ++; bLastWasSep = true; } else if ((ch == ',' && chLocalDecimalSep != ',') || ch == '\t' || ch == ';') { nCol ++; bLastWasSep = true; } else { if (bLastWasSep) { if (nCol == nXIndex) { nUsefulColsFound ++; dfX = CPLAtofDelim(pszPtr, chLocalDecimalSep); } else if (nCol == nYIndex) { nUsefulColsFound ++; dfY = CPLAtofDelim(pszPtr, chLocalDecimalSep); } else if (nCol == nZIndex) { nUsefulColsFound ++; dfZ = CPLAtofDelim(pszPtr, chLocalDecimalSep); if( nDataLineNum == 0 ) { dfMinZ = dfZ; dfMaxZ = dfZ; } else if( dfZ < dfMinZ ) { dfMinZ = dfZ; } else if( dfZ > dfMaxZ ) { dfMaxZ = dfZ; } if( dfZ < INT_MIN || dfZ > INT_MAX ) { eDT = GDT_Float32; } else { int nZ = static_cast<int>( dfZ ); if( static_cast<double>( nZ ) != dfZ ) { eDT = GDT_Float32; } else if ((eDT == GDT_Byte || eDT == GDT_Int16) && (nZ < 0 || nZ > 255)) { if (nZ < -32768 || nZ > 32767) eDT = GDT_Int32; else eDT = GDT_Int16; } } } } bLastWasSep = false; } pszPtr ++; } /* skip empty lines */ if (bLastWasSep && nCol == 0) { continue; } nDataLineNum ++; nCol ++; if (nCol < nMinTokens) { CPLError(CE_Failure, CPLE_AppDefined, "At line " CPL_FRMT_GIB ", found %d tokens. Expected %d at least", nLineNum, nCol, nMinTokens); VSIFCloseL(fp); return NULL; } if( nUsefulColsFound != 3 ) { CPLError(CE_Failure, CPLE_AppDefined, "At line " CPL_FRMT_GIB ", did not find X, Y and/or Z values", nLineNum); VSIFCloseL(fp); return NULL; } if (nDataLineNum == 1) { dfMinX = dfX; dfMaxX = dfX; dfMinY = dfY; dfMaxY = dfY; } else { double dfStepY = dfY - dfLastY; if( dfStepY == 0.0 ) { const double dfStepX = dfX - dfLastX; if( dfStepX <= 0 ) { CPLError(CE_Failure, CPLE_AppDefined, "Ungridded dataset: At line " CPL_FRMT_GIB ", X spacing was %f. Expected >0 value", nLineNum, dfStepX); VSIFCloseL(fp); return NULL; } if( std::find(adfStepX.begin(), adfStepX.end(), dfStepX) == adfStepX.end() ) { bool bAddNewValue = true; std::vector<double>::iterator oIter = adfStepX.begin(); std::vector<double> adfStepXNew; while( oIter != adfStepX.end() ) { if( fabs(( dfStepX - *oIter ) / dfStepX ) < RELATIVE_ERROR ) { double dfNewVal = *oIter; if( nCountStepX > 0 ) { // Update mean step /* n * mean(n) = (n-1) * mean(n-1) + val(n) mean(n) = mean(n-1) + (val(n) - mean(n-1)) / n */ nCountStepX ++; dfNewVal += ( dfStepX - *oIter ) / nCountStepX; } adfStepXNew.push_back( dfNewVal ); bAddNewValue = false; break; } else if( dfStepX < *oIter && fabs(*oIter - static_cast<int>(*oIter / dfStepX + 0.5) * dfStepX) / dfStepX < RELATIVE_ERROR ) { nCountStepX = -1; // disable update of mean ++ oIter; } else if( dfStepX > *oIter && fabs(dfStepX - static_cast<int>(dfStepX / *oIter + 0.5) * (*oIter)) / dfStepX < RELATIVE_ERROR ) { nCountStepX = -1; // disable update of mean bAddNewValue = false; adfStepXNew.push_back( *oIter ); break; } else { adfStepXNew.push_back( *oIter ); ++ oIter; } } adfStepX = adfStepXNew; if( bAddNewValue ) { CPLDebug("XYZ", "New stepX=%.15f", dfStepX); adfStepX.push_back(dfStepX); if( adfStepX.size() == 1 && nCountStepX == 0) { nCountStepX ++; } else if( adfStepX.size() == 2 ) { nCountStepX = -1; // disable update of mean } else if( adfStepX.size() == 10 ) { CPLError(CE_Failure, CPLE_AppDefined, "Ungridded dataset: too many stepX values"); VSIFCloseL(fp); return NULL; } } } } else { int bNewStepYSign = (dfStepY < 0.0) ? -1 : 1; if( bStepYSign == 0 ) bStepYSign = bNewStepYSign; else if( bStepYSign != bNewStepYSign ) { CPLError(CE_Failure, CPLE_AppDefined, "Ungridded dataset: At line " CPL_FRMT_GIB ", change of Y direction", nLineNum); VSIFCloseL(fp); return NULL; } if( bNewStepYSign < 0 ) dfStepY = -dfStepY; nCountStepY ++; if( adfStepY.empty() ) { adfStepY.push_back(dfStepY); } else if( fabs( (adfStepY[0] - dfStepY) / dfStepY ) > RELATIVE_ERROR ) { CPLDebug("XYZ", "New stepY=%.15f prev stepY=%.15f", dfStepY, adfStepY[0]); CPLError(CE_Failure, CPLE_AppDefined, "Ungridded dataset: At line " CPL_FRMT_GIB ", too many stepY values", nLineNum); VSIFCloseL(fp); return NULL; } else { // Update mean step adfStepY[0] += ( dfStepY - adfStepY[0] ) / nCountStepY; } } if (dfX < dfMinX) dfMinX = dfX; if (dfX > dfMaxX) dfMaxX = dfX; if (dfY < dfMinY) dfMinY = dfY; if (dfY > dfMaxY) dfMaxY = dfY; } dfLastX = dfX; dfLastY = dfY; } if (adfStepX.size() != 1) { CPLError(CE_Failure, CPLE_AppDefined, "Couldn't determine X spacing"); VSIFCloseL(fp); return NULL; } if (adfStepY.size() != 1) { CPLError(CE_Failure, CPLE_AppDefined, "Couldn't determine Y spacing"); VSIFCloseL(fp); return NULL; } const double dfXSize = 1 + ((dfMaxX - dfMinX) / adfStepX[0] + 0.5); const double dfYSize = 1 + ((dfMaxY - dfMinY) / adfStepY[0] + 0.5); if( dfXSize <= 0 || dfXSize > INT_MAX || dfYSize <= 0 || dfYSize > INT_MAX ) { CPLError(CE_Failure, CPLE_AppDefined, "Invalid dimensions"); VSIFCloseL(fp); return NULL; } const int nXSize = static_cast<int>(dfXSize); const int nYSize = static_cast<int>(dfYSize); const double dfStepX = (dfMaxX - dfMinX) / (nXSize - 1); const double dfStepY = (dfMaxY - dfMinY) / (nYSize - 1)* bStepYSign; #ifdef DEBUG_VERBOSE CPLDebug("XYZ", "minx=%f maxx=%f stepx=%f", dfMinX, dfMaxX, dfStepX); CPLDebug("XYZ", "miny=%f maxy=%f stepy=%f", dfMinY, dfMaxY, dfStepY); #endif if (nDataLineNum != static_cast<GIntBig>(nXSize) * nYSize) { bSameNumberOfValuesPerLine = false; } if (poOpenInfo->eAccess == GA_Update) { CPLError( CE_Failure, CPLE_NotSupported, "The XYZ driver does not support update access to existing" " datasets.\n" ); VSIFCloseL(fp); return NULL; } /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ XYZDataset *poDS = new XYZDataset(); poDS->fp = fp; poDS->bHasHeaderLine = bHasHeaderLine; poDS->nCommentLineCount = nCommentLineCount; poDS->chDecimalSep = chDecimalSep ? chDecimalSep : '.'; poDS->nXIndex = nXIndex; poDS->nYIndex = nYIndex; poDS->nZIndex = nZIndex; poDS->nMinTokens = nMinTokens; poDS->nRasterXSize = nXSize; poDS->nRasterYSize = nYSize; poDS->adfGeoTransform[0] = dfMinX - dfStepX / 2; poDS->adfGeoTransform[1] = dfStepX; poDS->adfGeoTransform[3] = (dfStepY < 0) ? dfMaxY - dfStepY / 2 : dfMinY - dfStepY / 2; poDS->adfGeoTransform[5] = dfStepY; poDS->bSameNumberOfValuesPerLine = bSameNumberOfValuesPerLine; poDS->dfMinZ = dfMinZ; poDS->dfMaxZ = dfMaxZ; #ifdef DEBUG_VERBOSE CPLDebug( "XYZ", "bSameNumberOfValuesPerLine = %d", bSameNumberOfValuesPerLine ); #endif if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize)) { delete poDS; return NULL; } /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ poDS->nBands = 1; for( int i = 0; i < poDS->nBands; i++ ) poDS->SetBand( i+1, new XYZRasterBand( poDS, i+1, eDT ) ); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Support overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return poDS; }