LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/gmt - ogrgmtlayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 391 263 67.3 %
Date: 2010-01-09 Functions: 15 12 80.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrgmtlayer.cpp 10645 2007-01-18 02:22:39Z warmerdam $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements OGRGmtLayer class.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2007, Frank Warmerdam <warmerdam@pobox.com>
      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 "ogr_gmt.h"
      31                 : #include "cpl_conv.h"
      32                 : #include "ogr_p.h"
      33                 : 
      34                 : CPL_CVSID("$Id: ogrgmtlayer.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
      35                 : 
      36                 : /************************************************************************/
      37                 : /*                            OGRGmtLayer()                             */
      38                 : /************************************************************************/
      39                 : 
      40               2 : OGRGmtLayer::OGRGmtLayer( const char * pszFilename, int bUpdate )
      41                 : 
      42                 : {
      43               2 :     poSRS = NULL;
      44                 :     
      45               2 :     iNextFID = 0;
      46               2 :     bValidFile = FALSE;
      47               2 :     bHeaderComplete = !bUpdate; // assume header complete in readonly mode.
      48               2 :     eWkbType = wkbUnknown;
      49               2 :     poFeatureDefn = NULL;
      50               2 :     papszKeyedValues = NULL;
      51                 : 
      52               2 :     this->bUpdate = bUpdate;
      53                 : 
      54               2 :     bRegionComplete = FALSE;
      55               2 :     nRegionOffset = 0;
      56                 : 
      57                 : /* -------------------------------------------------------------------- */
      58                 : /*      Open file.                                                      */
      59                 : /* -------------------------------------------------------------------- */
      60               2 :     if( bUpdate )
      61               1 :         fp = VSIFOpenL( pszFilename, "r+" );
      62                 :     else
      63               1 :         fp = VSIFOpenL( pszFilename, "r" );
      64                 :     
      65               2 :     if( fp == NULL )
      66               0 :         return;
      67                 : 
      68                 : /* -------------------------------------------------------------------- */
      69                 : /*      Read the header.                                                */
      70                 : /* -------------------------------------------------------------------- */
      71               2 :     CPLString osFieldNames, osFieldTypes, osGeometryType, osRegion;
      72               2 :     CPLString osWKT, osProj4, osEPSG;
      73               2 :     vsi_l_offset nStartOfLine = VSIFTellL(fp);
      74                 :     
      75              11 :     while( ReadLine() && osLine[0] == '#' )
      76                 :     {
      77                 :         int iKey;
      78                 : 
      79               8 :         if( strstr( osLine, "FEATURE_DATA" ) )
      80                 :         {
      81               1 :             bHeaderComplete = TRUE;
      82               1 :             ReadLine();
      83               1 :             break;
      84                 :         }
      85                 : 
      86               7 :         if( EQUALN( osLine, "# REGION_STUB ", 14 ) )
      87               1 :             nRegionOffset = nStartOfLine;
      88                 : 
      89              25 :         for( iKey = 0; 
      90              12 :              papszKeyedValues != NULL && papszKeyedValues[iKey] != NULL; 
      91                 :              iKey++ )
      92                 :         {
      93               6 :             if( papszKeyedValues[iKey][0] == 'N' )
      94               1 :                 osFieldNames = papszKeyedValues[iKey] + 1;
      95               6 :             if( papszKeyedValues[iKey][0] == 'T' )
      96               1 :                 osFieldTypes = papszKeyedValues[iKey] + 1;
      97               6 :             if( papszKeyedValues[iKey][0] == 'G' )
      98               1 :                 osGeometryType = papszKeyedValues[iKey] + 1;
      99               6 :             if( papszKeyedValues[iKey][0] == 'R' )
     100               1 :                 osRegion = papszKeyedValues[iKey] + 1;
     101               6 :             if( papszKeyedValues[iKey][0] == 'J' )
     102                 :             {
     103               0 :                 CPLString osArg = papszKeyedValues[iKey] + 2;
     104               0 :                 if( osArg[0] == '"' && osArg[osArg.length()-1] == '"' )
     105                 :                 {
     106               0 :                     osArg = osArg.substr(1,osArg.length()-2);
     107                 :                     char *pszArg = CPLUnescapeString(osArg, NULL,
     108               0 :                                                      CPLES_BackslashQuotable);
     109               0 :                     osArg = pszArg;
     110               0 :                     CPLFree( pszArg );
     111                 :                 }
     112                 :                     
     113               0 :                 if( papszKeyedValues[iKey][1] == 'e' )
     114               0 :                     osEPSG = osArg;
     115               0 :                 if( papszKeyedValues[iKey][1] == 'p' )
     116               0 :                     osProj4 = osArg;
     117               0 :                 if( papszKeyedValues[iKey][1] == 'w' )
     118               0 :                     osWKT = osArg;
     119                 :             }
     120                 :         }
     121                 : 
     122               7 :         nStartOfLine = VSIFTellL(fp);
     123                 :     }
     124                 : 
     125                 : /* -------------------------------------------------------------------- */
     126                 : /*      Handle coordinate system.                                       */
     127                 : /* -------------------------------------------------------------------- */
     128               2 :     if( osWKT.length() )
     129                 :     {
     130               0 :         char *pszWKT = (char *) osWKT.c_str();
     131                 : 
     132               0 :         poSRS = new OGRSpatialReference();
     133               0 :         if( poSRS->importFromWkt(&pszWKT) != OGRERR_NONE )
     134                 :         {
     135               0 :             delete poSRS;
     136               0 :             poSRS = NULL;
     137                 :         }
     138                 :     }
     139               2 :     else if( osEPSG.length() )
     140                 :     {
     141               0 :         poSRS = new OGRSpatialReference();
     142               0 :         if( poSRS->importFromEPSG( atoi(osEPSG) ) != OGRERR_NONE )
     143                 :         {
     144               0 :             delete poSRS;
     145               0 :             poSRS = NULL;
     146                 :         }
     147                 :     }
     148               2 :     else if( osProj4.length() )
     149                 :     {
     150               0 :         poSRS = new OGRSpatialReference();
     151               0 :         if( poSRS->importFromProj4( osProj4 ) != OGRERR_NONE )
     152                 :         {
     153               0 :             delete poSRS;
     154               0 :             poSRS = NULL;
     155                 :         }
     156                 :     }
     157                 : 
     158                 : /* -------------------------------------------------------------------- */
     159                 : /*      Create the feature definition, and set the geometry type, if    */
     160                 : /*      known.                                                          */
     161                 : /* -------------------------------------------------------------------- */
     162               2 :     poFeatureDefn = new OGRFeatureDefn( CPLGetBasename(pszFilename) );
     163               2 :     poFeatureDefn->Reference();
     164                 : 
     165               2 :     if( osGeometryType == "POINT" )
     166               0 :         poFeatureDefn->SetGeomType( wkbPoint );
     167               2 :     else if( osGeometryType == "MULTIPOINT" )
     168               0 :         poFeatureDefn->SetGeomType( wkbMultiPoint );
     169               2 :     else if( osGeometryType == "LINESTRING" )
     170               0 :         poFeatureDefn->SetGeomType( wkbLineString );
     171               2 :     else if( osGeometryType == "MULTILINESTRING" )
     172               0 :         poFeatureDefn->SetGeomType( wkbMultiLineString );
     173               2 :     else if( osGeometryType == "POLYGON" )
     174               1 :         poFeatureDefn->SetGeomType( wkbPolygon );
     175               1 :     else if( osGeometryType == "MULTIPOLYGON" )
     176               0 :         poFeatureDefn->SetGeomType( wkbMultiPolygon );
     177                 : 
     178                 : /* -------------------------------------------------------------------- */
     179                 : /*      Process a region line.                                          */
     180                 : /* -------------------------------------------------------------------- */
     181               2 :     if( osRegion.length() > 0 )
     182                 :     {
     183                 :         char **papszTokens = CSLTokenizeStringComplex( osRegion.c_str() + 1,
     184               1 :                                                        "/", FALSE, FALSE );
     185                 :         
     186               1 :         if( CSLCount(papszTokens) == 4 )
     187                 :         {
     188               1 :             sRegion.MinX = CPLAtofM(papszTokens[0]);
     189               1 :             sRegion.MaxX = CPLAtofM(papszTokens[1]);
     190               1 :             sRegion.MinY = CPLAtofM(papszTokens[2]);
     191               1 :             sRegion.MaxY = CPLAtofM(papszTokens[3]);
     192                 :         }
     193                 : 
     194               1 :         bRegionComplete = TRUE;
     195                 : 
     196               1 :         CSLDestroy( papszTokens );
     197                 :     }
     198                 : 
     199                 : /* -------------------------------------------------------------------- */
     200                 : /*      Process fields.                                                 */
     201                 : /* -------------------------------------------------------------------- */
     202               2 :     if( osFieldNames.length() || osFieldTypes.length() )
     203                 :     {
     204                 :         char **papszFN = CSLTokenizeStringComplex( osFieldNames, "|", 
     205               1 :                                                    TRUE, TRUE );
     206                 :         char **papszFT = CSLTokenizeStringComplex( osFieldTypes, "|", 
     207               1 :                                                    TRUE, TRUE );
     208               1 :         int nFieldCount = MAX(CSLCount(papszFN),CSLCount(papszFT));
     209                 :         int iField;
     210                 : 
     211               4 :         for( iField = 0; iField < nFieldCount; iField++ )
     212                 :         {
     213               3 :             OGRFieldDefn oField("", OFTString );
     214                 : 
     215               3 :             if( iField < CSLCount(papszFN) )
     216               3 :                 oField.SetName( papszFN[iField] );
     217                 :             else
     218               0 :                 oField.SetName( CPLString().Printf( "Field_%d", iField+1 ));
     219                 : 
     220               3 :             if( iField < CSLCount(papszFT) )
     221                 :             {
     222               3 :                 if( EQUAL(papszFT[iField],"integer") )
     223               1 :                     oField.SetType( OFTInteger );
     224               2 :                 else if( EQUAL(papszFT[iField],"double") )
     225               1 :                     oField.SetType( OFTReal );
     226               1 :                 else if( EQUAL(papszFT[iField],"datetime") )
     227               0 :                     oField.SetType( OFTDateTime );
     228                 :             }
     229                 : 
     230               3 :             poFeatureDefn->AddFieldDefn( &oField );
     231                 :         }
     232                 : 
     233               1 :         CSLDestroy( papszFN );
     234               1 :         CSLDestroy( papszFT );
     235                 :     }
     236                 : 
     237               2 :     bValidFile = TRUE;
     238               0 : }
     239                 : 
     240                 : /************************************************************************/
     241                 : /*                           ~OGRGmtLayer()                           */
     242                 : /************************************************************************/
     243                 : 
     244               4 : OGRGmtLayer::~OGRGmtLayer()
     245                 : 
     246                 : {
     247               2 :     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     248                 :     {
     249                 :         CPLDebug( "Gmt", "%d features read on layer '%s'.",
     250                 :                   (int) m_nFeaturesRead, 
     251               1 :                   poFeatureDefn->GetName() );
     252                 :     }
     253                 : 
     254                 : /* -------------------------------------------------------------------- */
     255                 : /*      Write out the region bounds if we know where they go, and we    */
     256                 : /*      are in update mode.                                             */
     257                 : /* -------------------------------------------------------------------- */
     258               2 :     if( nRegionOffset != 0 && bUpdate )
     259                 :     {
     260               1 :         VSIFSeekL( fp, nRegionOffset, SEEK_SET );
     261                 :         VSIFPrintfL( fp, "# @R%.12g/%.12g/%.12g/%.12g", 
     262                 :                      sRegion.MinX, 
     263                 :                      sRegion.MaxX,
     264                 :                      sRegion.MinY,
     265               1 :                      sRegion.MaxY );
     266                 :     }
     267                 :     
     268                 : /* -------------------------------------------------------------------- */
     269                 : /*      Clean up.                                                       */
     270                 : /* -------------------------------------------------------------------- */
     271               2 :     CSLDestroy( papszKeyedValues );
     272                 : 
     273               2 :     if( poFeatureDefn )
     274               2 :         poFeatureDefn->Release();
     275                 : 
     276               2 :     if( poSRS )
     277               0 :         poSRS->Release();
     278                 : 
     279               2 :     if( fp != NULL )
     280               2 :         VSIFCloseL( fp );
     281               4 : }
     282                 : 
     283                 : /************************************************************************/
     284                 : /*                              ReadLine()                              */
     285                 : /*                                                                      */
     286                 : /*      Read a line into osLine.  If it is a comment line with @        */
     287                 : /*      keyed values, parse out the keyed values into                   */
     288                 : /*      papszKeyedValues.                                               */
     289                 : /************************************************************************/
     290                 : 
     291             621 : int OGRGmtLayer::ReadLine()
     292                 : 
     293                 : {
     294                 : /* -------------------------------------------------------------------- */
     295                 : /*      Clear last line.                                                */
     296                 : /* -------------------------------------------------------------------- */
     297             621 :     osLine.erase();
     298             621 :     if( papszKeyedValues )
     299                 :     {
     300              87 :         CSLDestroy( papszKeyedValues );
     301              87 :         papszKeyedValues = NULL;
     302                 :     }
     303                 :     
     304                 : /* -------------------------------------------------------------------- */
     305                 : /*      Read newline.                                                   */
     306                 : /* -------------------------------------------------------------------- */
     307             621 :     const char *pszLine = CPLReadLineL( fp );
     308             621 :     if( pszLine == NULL )
     309               3 :         return FALSE; // end of file.
     310                 : 
     311             618 :     osLine = pszLine;
     312                 : 
     313                 : /* -------------------------------------------------------------------- */
     314                 : /*      If this is a comment line with keyed values, parse them.        */
     315                 : /* -------------------------------------------------------------------- */
     316                 :     size_t i;
     317                 : 
     318             708 :     if( osLine[0] != '#' || osLine.find_first_of('@') == std::string::npos )
     319             531 :         return TRUE;
     320                 : 
     321             398 :     for( i = 0; i < osLine.length(); i++ )
     322                 :     {
     323             311 :         if( osLine[i] == '@' )
     324                 :         {
     325                 :             size_t iValEnd;
     326              87 :             int bInQuotes = FALSE;
     327                 : 
     328            1153 :             for( iValEnd = i+2; iValEnd < osLine.length(); iValEnd++ )
     329                 :             {
     330            1068 :                 if( !bInQuotes && isspace((unsigned char)osLine[iValEnd]) )
     331               2 :                     break;
     332                 : 
     333            1066 :                 if( bInQuotes && osLine[iValEnd] == '\\' 
     334                 :                     && iValEnd < osLine.length()-1 )
     335                 :                 {
     336               0 :                     iValEnd++;
     337                 :                 }
     338            1066 :                 else if( osLine[iValEnd] == '"' )
     339               0 :                     bInQuotes = !bInQuotes;
     340                 :             }
     341                 : 
     342              87 :             CPLString osValue = osLine.substr(i+2,iValEnd-i-2);
     343                 : 
     344                 :             // Unecape contents
     345                 :             char *pszUEValue = CPLUnescapeString( osValue, NULL, 
     346              87 :                                                   CPLES_BackslashQuotable );
     347                 :             
     348              87 :             CPLString osKeyValue = osLine.substr(i+1,1);
     349              87 :             osKeyValue += pszUEValue;
     350              87 :             CPLFree( pszUEValue );
     351              87 :             papszKeyedValues = CSLAddString( papszKeyedValues, osKeyValue );
     352                 : 
     353              87 :             i = iValEnd;
     354                 :         }
     355                 :     }
     356                 : 
     357              87 :     return TRUE;
     358                 : }
     359                 : 
     360                 : /************************************************************************/
     361                 : /*                            ResetReading()                            */
     362                 : /************************************************************************/
     363                 : 
     364               2 : void OGRGmtLayer::ResetReading()
     365                 : 
     366                 : {
     367               2 :     if( iNextFID != 0 )
     368                 :     {
     369               1 :         iNextFID = 0;
     370               1 :         VSIFSeekL( fp, 0, SEEK_SET );
     371               1 :         ReadLine();
     372                 :     }
     373               2 : }
     374                 : 
     375                 : /************************************************************************/
     376                 : /*                          ScanAheadForHole()                          */
     377                 : /*                                                                      */
     378                 : /*      Scan ahead to see if the next geometry is a hole.  If so        */
     379                 : /*      return TRUE, otherwise seek back to where we were and return    */
     380                 : /*      FALSE.                                                          */
     381                 : /************************************************************************/
     382                 : 
     383              18 : int OGRGmtLayer::ScanAheadForHole()
     384                 : 
     385                 : {
     386              18 :     CPLString osSavedLine = osLine;
     387              18 :     vsi_l_offset nSavedLocation = VSIFTellL( fp );
     388                 : 
     389              72 :     while( ReadLine() && osLine[0] == '#' )
     390                 :     {
     391              36 :         if( papszKeyedValues != NULL && papszKeyedValues[0][0] == 'H' )
     392               0 :             return TRUE;
     393                 :     }
     394                 : 
     395              18 :     VSIFSeekL( fp, nSavedLocation, SEEK_SET );
     396              18 :     osLine = osSavedLine;
     397                 : 
     398                 :     // We don't actually restore papszKeyedValues, but we 
     399                 :     // assume it doesn't matter since this method is only called
     400                 :     // when processing the '>' line.
     401                 : 
     402              18 :     return FALSE;
     403                 : }
     404                 : 
     405                 : /************************************************************************/
     406                 : /*                         GetNextRawFeature()                          */
     407                 : /************************************************************************/
     408                 : 
     409              21 : OGRFeature *OGRGmtLayer::GetNextRawFeature()
     410                 : 
     411                 : {
     412                 :     int  bMultiVertex = 
     413                 :         poFeatureDefn->GetGeomType() != wkbPoint
     414              21 :         && poFeatureDefn->GetGeomType() != wkbUnknown;
     415              21 :     CPLString osFieldData;
     416              21 :     OGRGeometry *poGeom = NULL;
     417                 : 
     418                 : /* -------------------------------------------------------------------- */
     419                 : /*      Read lines associated with this feature.                        */
     420                 : /* -------------------------------------------------------------------- */
     421              21 :     int iChild = 0;
     422                 : 
     423             556 :     for( ; TRUE; ReadLine() )
     424                 :     {
     425             577 :         if( osLine.length() == 0 )
     426               3 :             break;
     427                 : 
     428             574 :         if( osLine[0] == '>' )
     429                 :         {
     430              56 :             if( poGeom != NULL 
     431              18 :                 && wkbFlatten(poGeom->getGeometryType()) == wkbPolygon
     432                 :                 && ScanAheadForHole() )
     433                 :             {
     434               0 :                 iChild++;
     435                 :             }
     436              38 :             else if( poGeom != NULL )
     437              18 :                 break;
     438              20 :             else if( poFeatureDefn->GetGeomType() == wkbUnknown )
     439                 :             {
     440               0 :                 poFeatureDefn->SetGeomType( wkbLineString );
     441               0 :                 bMultiVertex = TRUE;
     442                 :             }
     443                 :         }
     444             536 :         else if( osLine[0] == '#' )
     445                 :         {
     446                 :             int i;
     447             181 :             for( i = 0; 
     448              90 :                  papszKeyedValues != NULL && papszKeyedValues[i] != NULL; 
     449                 :                  i++ )
     450                 :             {
     451              45 :                 if( papszKeyedValues[i][0] == 'D' )
     452              20 :                     osFieldData = papszKeyedValues[i] + 1;
     453                 :             }
     454                 :         }
     455                 :         else
     456                 :         {
     457                 :             // Parse point line. 
     458             490 :             double dfX, dfY, dfZ = 0.0;
     459             490 :             int nDim = sscanf( osLine, "%lf %lf %lf", &dfX, &dfY, &dfZ );
     460                 :                 
     461             490 :             if( nDim >= 2 )
     462                 :             {
     463             490 :                 if( poGeom == NULL )
     464                 :                 {
     465              20 :                     switch( poFeatureDefn->GetGeomType() )
     466                 :                     {
     467                 :                       case wkbLineString:
     468               0 :                         poGeom = new OGRLineString();
     469               0 :                         break;
     470                 :                     
     471                 :                       case wkbPolygon:
     472              20 :                         poGeom = new OGRPolygon();
     473              20 :                         break;
     474                 :                     
     475                 :                       case wkbMultiPolygon:
     476               0 :                         poGeom = new OGRMultiPolygon();
     477               0 :                         break;
     478                 :                     
     479                 :                       case wkbMultiPoint:
     480               0 :                         poGeom = new OGRMultiPoint();
     481               0 :                         break;
     482                 : 
     483                 :                       case wkbPoint:
     484                 :                       case wkbUnknown:
     485                 :                       default:
     486               0 :                         poGeom = new OGRPoint();
     487                 :                         break;
     488                 :                     }
     489                 : 
     490                 :                 }
     491                 : 
     492             490 :                 switch( wkbFlatten(poGeom->getGeometryType()) )
     493                 :                 {
     494                 :                   case wkbPoint:
     495               0 :                     ((OGRPoint *) poGeom)->setX( dfX );
     496               0 :                     ((OGRPoint *) poGeom)->setY( dfY );
     497               0 :                     if( nDim == 3 )
     498               0 :                         ((OGRPoint *) poGeom)->setZ( dfZ );
     499               0 :                     break;
     500                 : 
     501                 :                   case wkbLineString:
     502               0 :                     if( nDim == 3 )
     503               0 :                         ((OGRLineString *)poGeom)->addPoint(dfX,dfY,dfZ);
     504                 :                     else
     505               0 :                         ((OGRLineString *)poGeom)->addPoint(dfX,dfY);
     506               0 :                     break;
     507                 : 
     508                 :                   case wkbPolygon:
     509                 :                   {
     510             490 :                       OGRPolygon *poPoly = (OGRPolygon *) poGeom;
     511                 :                       OGRLinearRing *poRing;
     512                 : 
     513             490 :                       if( iChild == 0 )
     514             490 :                           poRing = poPoly->getExteriorRing();
     515                 :                       else
     516               0 :                           poRing = poPoly->getInteriorRing(iChild-1);
     517             490 :                       if( poRing == NULL )
     518                 :                       {
     519              20 :                           poRing = new OGRLinearRing();
     520              20 :                           poPoly->addRingDirectly( poRing );
     521                 :                       }
     522                 :                       
     523             490 :                       if( nDim == 3 )
     524               0 :                         poRing->addPoint(dfX,dfY,dfZ);
     525                 :                       else
     526             490 :                         poRing->addPoint(dfX,dfY);
     527                 :                   }
     528                 :                   break;
     529                 : 
     530                 :                   default:
     531                 :                     CPLAssert( FALSE );
     532                 :                 }
     533                 :             }
     534                 :         }
     535                 : 
     536             556 :         if( poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint )
     537                 :         {
     538               0 :             ReadLine();
     539               0 :             break;
     540                 :         }
     541                 :     }
     542                 : 
     543              21 :     if( poGeom == NULL )
     544               1 :         return NULL;
     545                 : 
     546                 : /* -------------------------------------------------------------------- */
     547                 : /*      Create feature.                                                 */
     548                 : /* -------------------------------------------------------------------- */
     549              20 :     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
     550              20 :     poFeature->SetGeometryDirectly( poGeom );
     551              20 :     poFeature->SetFID( iNextFID++ );
     552                 : 
     553                 : /* -------------------------------------------------------------------- */
     554                 : /*      Process field values.                                           */
     555                 : /* -------------------------------------------------------------------- */
     556              20 :     char **papszFD = CSLTokenizeStringComplex( osFieldData, "|", TRUE, TRUE );
     557                 :     int iField; 
     558                 : 
     559              80 :     for( iField = 0; papszFD != NULL && papszFD[iField] != NULL; iField++ )
     560                 :     {
     561              60 :         if( iField >= poFeatureDefn->GetFieldCount() )
     562               0 :             break;
     563                 : 
     564              60 :         poFeature->SetField( iField, papszFD[iField] );
     565                 :     }
     566                 : 
     567              20 :     CSLDestroy( papszFD );
     568                 : 
     569              20 :     m_nFeaturesRead++;
     570                 : 
     571              20 :     return poFeature;
     572                 : }
     573                 : 
     574                 : /************************************************************************/
     575                 : /*                           GetNextFeature()                           */
     576                 : /************************************************************************/
     577                 : 
     578              21 : OGRFeature *OGRGmtLayer::GetNextFeature()
     579                 : 
     580                 : {
     581               5 :     while( TRUE )
     582                 :     {
     583              21 :         OGRFeature *poFeature = GetNextRawFeature();
     584                 : 
     585              21 :         if( poFeature == NULL )
     586               1 :             return NULL;
     587                 : 
     588              20 :         if( (m_poFilterGeom == NULL
     589                 :              || FilterGeometry( poFeature->GetGeometryRef() ) )
     590                 :             && (m_poAttrQuery == NULL
     591                 :                 || m_poAttrQuery->Evaluate( poFeature ) ) )
     592                 :         {
     593              15 :             return poFeature;
     594                 :         }
     595                 :         else
     596                 :         {
     597               5 :             delete poFeature;
     598                 :         }
     599                 :     }
     600                 : 
     601                 :     return NULL;
     602                 : }
     603                 : 
     604                 : /************************************************************************/
     605                 : /*                           CompleteHeader()                           */
     606                 : /*                                                                      */
     607                 : /*      Finish writing out the header with field definitions and the    */
     608                 : /*      layer geometry type.                                            */
     609                 : /************************************************************************/
     610                 : 
     611               1 : OGRErr OGRGmtLayer::CompleteHeader( OGRGeometry *poThisGeom )
     612                 : 
     613                 : {
     614                 : /* -------------------------------------------------------------------- */
     615                 : /*      If we don't already have a geometry type, try to work one       */
     616                 : /*      out and write it now.                                           */
     617                 : /* -------------------------------------------------------------------- */
     618               1 :     if( poFeatureDefn->GetGeomType() == wkbUnknown 
     619                 :         && poThisGeom != NULL )
     620                 :     {
     621                 :         const char *pszGeom;
     622                 : 
     623               1 :         poFeatureDefn->SetGeomType(wkbFlatten(poThisGeom->getGeometryType()));
     624                 : 
     625               1 :         switch( wkbFlatten(poFeatureDefn->GetGeomType()) )
     626                 :         {
     627                 :           case wkbPoint:
     628               0 :             pszGeom = " @GPOINT";
     629               0 :             break;
     630                 :           case wkbLineString:
     631               0 :             pszGeom = " @GLINESTRING";
     632               0 :             break;
     633                 :           case wkbPolygon:
     634               1 :             pszGeom = " @GPOLYGON";
     635               1 :             break;
     636                 :           case wkbMultiPoint:
     637               0 :             pszGeom = " @GMULTIPOINT";
     638               0 :             break;
     639                 :           case wkbMultiLineString:
     640               0 :             pszGeom = " @GMULTILINESTRING";
     641               0 :             break;
     642                 :           case wkbMultiPolygon:
     643               0 :             pszGeom = " @GMULTIPOLYGON";
     644               0 :             break;
     645                 :           default:
     646               0 :             pszGeom = "";
     647                 :             break;
     648                 :         }
     649                 :         
     650               1 :         VSIFPrintfL( fp, "#%s\n", pszGeom );
     651                 :     }
     652                 : 
     653                 : /* -------------------------------------------------------------------- */
     654                 : /*      Prepare and write the field names and types.                    */
     655                 : /* -------------------------------------------------------------------- */
     656               1 :     CPLString osFieldNames, osFieldTypes;
     657                 :         
     658                 :     int iField;
     659                 : 
     660               4 :     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     661                 :     {
     662               3 :         if( iField > 0 )
     663                 :         {
     664               2 :             osFieldNames += "|";
     665               2 :             osFieldTypes += "|";
     666                 :         }
     667                 : 
     668               3 :         osFieldNames += poFeatureDefn->GetFieldDefn(iField)->GetNameRef();
     669               3 :         switch( poFeatureDefn->GetFieldDefn(iField)->GetType() )
     670                 :         {
     671                 :           case OFTInteger:
     672               1 :             osFieldTypes += "integer";
     673               1 :             break;
     674                 :                 
     675                 :           case OFTReal:
     676               1 :             osFieldTypes += "double";
     677               1 :             break;
     678                 :                 
     679                 :           case OFTDateTime:
     680               0 :             osFieldTypes += "datetime";
     681               0 :             break;
     682                 :                 
     683                 :           default:
     684               1 :             osFieldTypes += "string";
     685                 :             break;
     686                 :         }
     687                 :     }
     688                 : 
     689               1 :     if( poFeatureDefn->GetFieldCount() > 0 )
     690                 :     {
     691               1 :         VSIFPrintfL( fp, "# @N%s\n", osFieldNames.c_str() );
     692               1 :         VSIFPrintfL( fp, "# @T%s\n", osFieldTypes.c_str() );
     693                 :     }
     694                 : 
     695                 : /* -------------------------------------------------------------------- */
     696                 : /*      Mark the end of the header, and start of feature data.          */
     697                 : /* -------------------------------------------------------------------- */
     698               1 :     VSIFPrintfL( fp, "# FEATURE_DATA\n" );
     699                 : 
     700               1 :     bHeaderComplete = TRUE;
     701               1 :     bRegionComplete = TRUE; // no feature written, so we know them all!
     702                 : 
     703               1 :     return OGRERR_NONE;
     704                 : }
     705                 : 
     706                 : /************************************************************************/
     707                 : /*                           CreateFeature()                            */
     708                 : /************************************************************************/
     709                 : 
     710              10 : OGRErr OGRGmtLayer::CreateFeature( OGRFeature *poFeature )
     711                 : 
     712                 : {
     713              10 :     if( !bUpdate )
     714                 :     {
     715                 :         CPLError( CE_Failure, CPLE_NoWriteAccess, 
     716               0 :                   "Can't create features on read-only dataset." );
     717               0 :         return OGRERR_FAILURE;
     718                 :     }
     719                 : 
     720                 : /* -------------------------------------------------------------------- */
     721                 : /*      Do we need to write the header describing the fields?           */
     722                 : /* -------------------------------------------------------------------- */
     723              10 :     if( !bHeaderComplete )
     724                 :     {
     725               1 :         OGRErr eErr = CompleteHeader( poFeature->GetGeometryRef() );
     726                 : 
     727               1 :         if( eErr != OGRERR_NONE )
     728               0 :             return eErr;
     729                 :     }
     730                 : 
     731                 : /* -------------------------------------------------------------------- */
     732                 : /*      Write out the feature                                           */
     733                 : /* -------------------------------------------------------------------- */
     734              10 :     OGRGeometry *poGeom = poFeature->GetGeometryRef();
     735                 :     
     736              10 :     if( poGeom == NULL )
     737                 :     {
     738                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     739               0 :                   "Features without geometry not supported by GMT writer." );
     740               0 :         return OGRERR_FAILURE;
     741                 :     }
     742                 : 
     743              10 :     if( poFeatureDefn->GetGeomType() == wkbUnknown )
     744               0 :         poFeatureDefn->SetGeomType(wkbFlatten(poGeom->getGeometryType()));
     745                 : 
     746                 :     // Do we need a vertex collection marker grouping vertices. 
     747              10 :     if( poFeatureDefn->GetGeomType() != wkbPoint )
     748              10 :         VSIFPrintfL( fp, ">\n" );
     749                 : 
     750                 : /* -------------------------------------------------------------------- */
     751                 : /*      Write feature properties()                                      */
     752                 : /* -------------------------------------------------------------------- */
     753              10 :     if( poFeatureDefn->GetFieldCount() > 0 )
     754                 :     {
     755                 :         int iField;
     756              10 :         CPLString osFieldData;
     757                 : 
     758              40 :         for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     759                 :         {
     760              30 :             OGRFieldType eFType=poFeatureDefn->GetFieldDefn(iField)->GetType();
     761              30 :             const char *pszRawValue = poFeature->GetFieldAsString(iField);
     762                 :             char *pszEscapedVal;
     763                 : 
     764              30 :             if( iField > 0 )
     765              20 :                 osFieldData += "|";
     766                 : 
     767                 :             // We don't want prefix spaces for numeric values.
     768              30 :             if( eFType == OFTInteger || eFType == OFTReal )
     769              40 :                 while( *pszRawValue == ' ' )
     770               0 :                     pszRawValue++;
     771                 : 
     772              30 :             if( strchr(pszRawValue,' ') || strchr(pszRawValue,'|') 
     773                 :                 || strchr(pszRawValue, '\t') || strchr(pszRawValue, '\n') )
     774                 :             {
     775                 :                 pszEscapedVal = 
     776                 :                     CPLEscapeString( pszRawValue, 
     777               0 :                                      -1, CPLES_BackslashQuotable );
     778                 :                 
     779               0 :                 osFieldData += "\"";
     780               0 :                 osFieldData += pszEscapedVal;
     781               0 :                 osFieldData += "\"";
     782               0 :                 CPLFree( pszEscapedVal );
     783                 :             }
     784                 :             else
     785              30 :                 osFieldData += pszRawValue;
     786                 :         }
     787                 : 
     788              10 :         VSIFPrintfL( fp, "# @D%s\n", osFieldData.c_str() );
     789                 :     }
     790                 : 
     791                 : /* -------------------------------------------------------------------- */
     792                 : /*      Write Geometry                                                  */
     793                 : /* -------------------------------------------------------------------- */
     794              10 :     return WriteGeometry( (OGRGeometryH) poGeom, TRUE );
     795                 : }
     796                 : 
     797                 : /************************************************************************/
     798                 : /*                           WriteGeometry()                            */
     799                 : /*                                                                      */
     800                 : /*      Write a geometry to the file.  If bHaveAngle is TRUE it         */
     801                 : /*      means the angle bracket preceeding the point stream has         */
     802                 : /*      already been written out.                                       */
     803                 : /*                                                                      */
     804                 : /*      We use the C API for geometry access because of it's            */
     805                 : /*      simplified access to vertices and children geometries.          */
     806                 : /************************************************************************/
     807                 : 
     808              20 : OGRErr OGRGmtLayer::WriteGeometry( OGRGeometryH hGeom, int bHaveAngle )
     809                 : 
     810                 : {
     811                 : /* -------------------------------------------------------------------- */
     812                 : /*      This is a geometry with sub-geometries.                         */
     813                 : /* -------------------------------------------------------------------- */
     814              20 :     if( OGR_G_GetGeometryCount( hGeom ) > 0 )
     815                 :     {
     816                 :         int iGeom;
     817              10 :         OGRErr eErr = OGRERR_NONE;
     818                 :         
     819              20 :         for( iGeom = 0; 
     820                 :              iGeom < OGR_G_GetGeometryCount(hGeom) && eErr == OGRERR_NONE;
     821                 :              iGeom++ )
     822                 :         {
     823                 :             // We need to emit polygon @P and @H items while we still
     824                 :             // know this is a polygon and which is the outer and inner
     825                 :             // ring. 
     826              10 :             if( wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbPolygon )
     827                 :             {
     828              10 :                 if( !bHaveAngle )
     829                 :                 {
     830               0 :                     VSIFPrintfL( fp, ">\n" );
     831               0 :                     bHaveAngle = TRUE;
     832                 :                 }
     833              10 :                 if( iGeom == 0 )
     834              10 :                     VSIFPrintfL( fp, "# @P\n" );
     835                 :                 else
     836               0 :                     VSIFPrintfL( fp, "# @H\n" );
     837                 :             }
     838                 : 
     839                 :             eErr = WriteGeometry( OGR_G_GetGeometryRef( hGeom, iGeom ), 
     840              10 :                                   bHaveAngle );
     841              10 :             bHaveAngle = FALSE;
     842                 :         }
     843              10 :         return eErr;
     844                 :     }
     845                 : 
     846                 : /* -------------------------------------------------------------------- */
     847                 : /*      If this is not a point we need to have an angle bracket to      */
     848                 : /*      mark the vertex list.                                           */
     849                 : /* -------------------------------------------------------------------- */
     850              10 :     if( wkbFlatten(OGR_G_GetGeometryType(hGeom)) != wkbPoint 
     851                 :         && !bHaveAngle )
     852               0 :         VSIFPrintfL( fp, ">\n" );
     853                 : 
     854                 : /* -------------------------------------------------------------------- */
     855                 : /*      Dump vertices.                                                  */
     856                 : /* -------------------------------------------------------------------- */
     857              10 :     int iPoint, nPointCount = OGR_G_GetPointCount(hGeom);
     858              10 :     int nDim = OGR_G_GetCoordinateDimension(hGeom);
     859                 : 
     860             255 :     for( iPoint = 0; iPoint < nPointCount; iPoint++ )
     861                 :     {
     862                 :         char   szLine[128];
     863             245 :         double dfX = OGR_G_GetX( hGeom, iPoint );
     864             245 :         double dfY = OGR_G_GetY( hGeom, iPoint );
     865             245 :         double dfZ = OGR_G_GetZ( hGeom, iPoint );
     866                 : 
     867             245 :         sRegion.Merge( dfX, dfY );
     868             245 :         OGRMakeWktCoordinate( szLine, dfX, dfY, dfZ, nDim );
     869             245 :         if( VSIFPrintfL( fp, "%s\n", szLine ) < 1 )
     870                 :         {
     871                 :             CPLError( CE_Failure, CPLE_FileIO, 
     872                 :                       "Gmt write failure: %s", 
     873               0 :                       VSIStrerror( errno ) );
     874               0 :             return OGRERR_FAILURE;
     875                 :         }
     876                 :     }
     877                 : 
     878              10 :     return OGRERR_NONE;
     879                 : }
     880                 : 
     881                 : /************************************************************************/
     882                 : /*                             GetExtent()                              */
     883                 : /*                                                                      */
     884                 : /*      Fetch extent of the data currently stored in the dataset.       */
     885                 : /*      The bForce flag has no effect on SHO files since that value     */
     886                 : /*      is always in the header.                                        */
     887                 : /*                                                                      */
     888                 : /*      Returns OGRERR_NONE/OGRRERR_FAILURE.                            */
     889                 : /************************************************************************/
     890                 : 
     891               0 : OGRErr OGRGmtLayer::GetExtent (OGREnvelope *psExtent, int bForce)
     892                 : 
     893                 : {
     894               0 :     if( bRegionComplete && sRegion.IsInit() )
     895                 :     {
     896               0 :         *psExtent = sRegion;
     897               0 :         return OGRERR_NONE;
     898                 :     }
     899                 : 
     900               0 :     return OGRLayer::GetExtent( psExtent, bForce );
     901                 : }
     902                 : 
     903                 : /************************************************************************/
     904                 : /*                           TestCapability()                           */
     905                 : /************************************************************************/
     906                 : 
     907               0 : int OGRGmtLayer::TestCapability( const char * pszCap )
     908                 : 
     909                 : {
     910               0 :     if( EQUAL(pszCap,OLCRandomRead) )
     911               0 :         return FALSE;
     912                 : 
     913               0 :     else if( EQUAL(pszCap,OLCSequentialWrite) )
     914               0 :         return TRUE;
     915                 : 
     916               0 :     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
     917               0 :         return FALSE;
     918                 : 
     919               0 :     else if( EQUAL(pszCap,OLCFastGetExtent) )
     920               0 :         return bRegionComplete;
     921                 : 
     922               0 :     else if( EQUAL(pszCap,OLCCreateField) )
     923               0 :         return TRUE;
     924                 : 
     925                 :     else 
     926               0 :         return FALSE;
     927                 : }
     928                 : 
     929                 : /************************************************************************/
     930                 : /*                            CreateField()                             */
     931                 : /************************************************************************/
     932                 : 
     933               3 : OGRErr OGRGmtLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
     934                 : 
     935                 : {
     936               3 :     if( !bUpdate )
     937                 :     {
     938                 :         CPLError( CE_Failure, CPLE_NoWriteAccess, 
     939               0 :                   "Can't create fields on read-only dataset." );
     940               0 :         return OGRERR_FAILURE;
     941                 :     }
     942                 : 
     943               3 :     if( bHeaderComplete )
     944                 :     {
     945                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     946               0 :                   "Unable to create fields after features have been created.");
     947               0 :         return OGRERR_FAILURE;
     948                 :     }
     949                 : 
     950               3 :     switch( poField->GetType() )
     951                 :     {
     952                 :       case OFTInteger:
     953                 :       case OFTReal:
     954                 :       case OFTString:
     955                 :       case OFTDateTime:
     956               3 :         poFeatureDefn->AddFieldDefn( poField );
     957               3 :         return OGRERR_NONE;
     958                 :         break;
     959                 : 
     960                 :         break;
     961                 : 
     962                 :       default:
     963               0 :         if( !bApproxOK )
     964                 :         {
     965                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     966                 :                       "Field %s is of unsupported type %s.", 
     967                 :                       poField->GetNameRef(), 
     968               0 :                       poField->GetFieldTypeName( poField->GetType() ) );
     969               0 :             return OGRERR_FAILURE;
     970                 :         } 
     971               0 :         else if( poField->GetType() == OFTDate 
     972                 :                  || poField->GetType() == OFTTime )
     973                 :         {
     974               0 :             OGRFieldDefn oModDef( poField );
     975               0 :             oModDef.SetType( OFTDateTime );
     976               0 :             poFeatureDefn->AddFieldDefn( poField );
     977               0 :             return OGRERR_NONE;
     978                 :         }
     979                 :         else 
     980                 :         {
     981               0 :             OGRFieldDefn oModDef( poField );
     982               0 :             oModDef.SetType( OFTString );
     983               0 :             poFeatureDefn->AddFieldDefn( poField );
     984               0 :             return OGRERR_NONE;
     985                 :         }
     986                 :     }
     987                 : }
     988                 : 
     989                 : /************************************************************************/
     990                 : /*                           GetSpatialRef()                            */
     991                 : /************************************************************************/
     992                 : 
     993               0 : OGRSpatialReference *OGRGmtLayer::GetSpatialRef()
     994                 : 
     995                 : {
     996               0 :     return poSRS;
     997                 : }

Generated by: LCOV version 1.7