~ubuntu-branches/debian/sid/gdal/sid

« back to all changes in this revision

Viewing changes to ogr/ogrsf_frmts/gpx/ogrgpxlayer.cpp

  • Committer: Package Import Robot
  • Author(s): Francesco Paolo Lovergine
  • Date: 2012-05-07 15:04:42 UTC
  • mfrom: (5.5.16 experimental)
  • Revision ID: package-import@ubuntu.com-20120507150442-2eks97loeh6rq005
Tags: 1.9.0-1
* Ready for sid, starting transition.
* All symfiles updated to latest builds.
* Added dh_numpy call in debian/rules to depend on numpy ABI.
* Policy bumped to 3.9.3, no changes required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/******************************************************************************
2
 
 * $Id: ogrgpxlayer.cpp 17753 2009-10-04 18:41:53Z rouault $
 
2
 * $Id: ogrgpxlayer.cpp 20996 2010-10-28 18:38:15Z rouault $
3
3
 *
4
4
 * Project:  GPX Translator
5
5
 * Purpose:  Implements OGRGPXLayer class.
33
33
#include "cpl_minixml.h"
34
34
#include "ogr_p.h"
35
35
 
36
 
CPL_CVSID("$Id: ogrgpxlayer.cpp 17753 2009-10-04 18:41:53Z rouault $");
 
36
CPL_CVSID("$Id: ogrgpxlayer.cpp 20996 2010-10-28 18:38:15Z rouault $");
 
37
 
 
38
#define FLD_TRACK_FID       0
 
39
#define FLD_TRACK_SEG_ID    1
 
40
#define FLD_TRACK_PT_ID     2
 
41
#define FLD_TRACK_NAME      3
 
42
 
 
43
#define FLD_ROUTE_FID       0
 
44
#define FLD_ROUTE_PT_ID     1
 
45
#define FLD_ROUTE_NAME      2
37
46
 
38
47
/************************************************************************/
39
48
/*                            OGRGPXLayer()                             */
55
64
 
56
65
    eof = FALSE;
57
66
    nNextFID = 0;
58
 
    
 
67
 
59
68
    this->poDS = poDS;
60
69
    this->bWriteMode = bWriteMode;
61
70
    this->gpxGeomType = gpxGeomType;
89
98
        
90
99
        OGRFieldDefn oFieldTrackSegPointID((bShortNames) ? "trksegptid" : "track_seg_point_id", OFTInteger );
91
100
        poFeatureDefn->AddFieldDefn( &oFieldTrackSegPointID );
 
101
        
 
102
        if (bWriteMode)
 
103
        {
 
104
            OGRFieldDefn oFieldName("track_name", OFTString );
 
105
            poFeatureDefn->AddFieldDefn( &oFieldName );
 
106
        }
92
107
    }
93
108
    else if (gpxGeomType == GPX_ROUTE_POINT)
94
109
    {
98
113
        
99
114
        OGRFieldDefn oFieldRoutePointID((bShortNames) ? "rteptid" : "route_point_id", OFTInteger );
100
115
        poFeatureDefn->AddFieldDefn( &oFieldRoutePointID );
 
116
 
 
117
        if (bWriteMode)
 
118
        {
 
119
            OGRFieldDefn oFieldName("route_name", OFTString );
 
120
            poFeatureDefn->AddFieldDefn( &oFieldName );
 
121
        }
101
122
    }
102
123
 
 
124
    iFirstGPXField = poFeatureDefn->GetFieldCount();
 
125
 
103
126
    if (gpxGeomType == GPX_WPT ||
104
127
        gpxGeomType == GPX_TRACK_POINT ||
105
128
        gpxGeomType == GPX_ROUTE_POINT)
474
497
            if (gpxGeomType == GPX_ROUTE_POINT)
475
498
            {
476
499
                rtePtId++;
477
 
                poFeature->SetField( 0, rteFID-1);
478
 
                poFeature->SetField( 1, rtePtId-1);
 
500
                poFeature->SetField( FLD_ROUTE_FID, rteFID-1);
 
501
                poFeature->SetField( FLD_ROUTE_PT_ID, rtePtId-1);
479
502
            }
480
503
            else if (gpxGeomType == GPX_TRACK_POINT)
481
504
            {
482
505
                trkSegPtId++;
483
506
 
484
 
                poFeature->SetField( 0, trkFID-1);
485
 
                poFeature->SetField( 1, trkSegId-1);
486
 
                poFeature->SetField( 2, trkSegPtId-1);
 
507
                poFeature->SetField( FLD_TRACK_FID, trkFID-1);
 
508
                poFeature->SetField( FLD_TRACK_SEG_ID, trkSegId-1);
 
509
                poFeature->SetField( FLD_TRACK_PT_ID, trkSegPtId-1);
487
510
            }
488
511
        }
489
512
    }
1115
1138
/*                   OGRGPX_WriteXMLExtension()                          */
1116
1139
/************************************************************************/
1117
1140
 
1118
 
static int OGRGPX_WriteXMLExtension(FILE* fp,
1119
 
                                    const char* pszTagName,
1120
 
                                    const char* pszContent)
 
1141
int OGRGPXLayer::OGRGPX_WriteXMLExtension(const char* pszTagName,
 
1142
                                          const char* pszContent)
1121
1143
{
1122
1144
    CPLXMLNode* poXML = CPLParseXMLString(pszContent);
1123
1145
    if (poXML)
1135
1157
            
1136
1158
        /* Don't XML escape here */
1137
1159
        char *pszUTF8 = OGRGPX_GetUTF8String( pszContent );
1138
 
        VSIFPrintf(fp, "    <%s%s>%s</%s>\n",
 
1160
        poDS->PrintLine("    <%s%s>%s</%s>",
1139
1161
                   pszTagNameWithNS, (pszXMLNS) ? pszXMLNS : "", pszUTF8, pszTagNameWithNS);
1140
1162
        CPLFree(pszUTF8);
1141
1163
        
1152
1174
/*                      WriteFeatureAttributes()                        */
1153
1175
/************************************************************************/
1154
1176
 
1155
 
void OGRGPXLayer::WriteFeatureAttributes( OGRFeature *poFeature )
1156
 
{
1157
 
    FILE* fp = poDS->GetOutputFP();
 
1177
static void AddIdent(VSILFILE* fp, int nIdentLevel)
 
1178
{
 
1179
    int i;
 
1180
    for(i=0;i<nIdentLevel;i++)
 
1181
        VSIFPrintfL(fp, "  ");
 
1182
}
 
1183
 
 
1184
void OGRGPXLayer::WriteFeatureAttributes( OGRFeature *poFeature, int nIdentLevel )
 
1185
{
 
1186
    VSILFILE* fp = poDS->GetOutputFP();
1158
1187
    int i;
1159
1188
    
1160
1189
    /* Begin with standard GPX fields */
1161
 
    for(i=0;i<nGPXFields;i++)
 
1190
    for(i=iFirstGPXField;i<nGPXFields;i++)
1162
1191
    { 
1163
1192
        OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( i );
1164
1193
        if( poFeature->IsFieldSet( i ) )
1171
1200
                                                  &hour, &minute, &second, &TZFlag))
1172
1201
                {
1173
1202
                    char* pszDate = OGRGetXMLDateTime(year, month, day, hour, minute, second, TZFlag);
1174
 
                    VSIFPrintf(fp, "  <time>%s</time>\n", pszDate);
 
1203
                    AddIdent(fp, nIdentLevel);
 
1204
                    poDS->PrintLine("<time>%s</time>", pszDate);
1175
1205
                    CPLFree(pszDate);
1176
1206
                }
1177
1207
            }
1179
1209
            {
1180
1210
                if (strstr(pszName, "href"))
1181
1211
                {
1182
 
                    VSIFPrintf(fp, "  <link href=\"%s\">", poFeature->GetFieldAsString( i ));
 
1212
                    AddIdent(fp, nIdentLevel);
 
1213
                    VSIFPrintfL(fp, "<link href=\"%s\">", poFeature->GetFieldAsString( i ));
1183
1214
                    if( poFeature->IsFieldSet( i + 1 ) )
1184
 
                        VSIFPrintf(fp, "<text>%s</text>", poFeature->GetFieldAsString( i + 1 ));
 
1215
                        VSIFPrintfL(fp, "<text>%s</text>", poFeature->GetFieldAsString( i + 1 ));
1185
1216
                    if( poFeature->IsFieldSet( i + 2 ) )
1186
 
                        VSIFPrintf(fp, "<type>%s</type>", poFeature->GetFieldAsString( i + 2 ));
1187
 
                    VSIFPrintf(fp, "</link>\n");
 
1217
                        VSIFPrintfL(fp, "<type>%s</type>", poFeature->GetFieldAsString( i + 2 ));
 
1218
                    poDS->PrintLine("</link>");
1188
1219
                }
1189
1220
            }
 
1221
            else if (poFieldDefn->GetType() == OFTReal)
 
1222
            {
 
1223
                char szValue[64];
 
1224
                OGRFormatDouble(szValue, sizeof(szValue), poFeature->GetFieldAsDouble(i), '.');
 
1225
                AddIdent(fp, nIdentLevel);
 
1226
                poDS->PrintLine("<%s>%s</%s>", pszName, szValue, pszName);
 
1227
            }
1190
1228
            else
1191
1229
            {
1192
1230
                char* pszValue =
1193
1231
                        OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( i ));
1194
 
                VSIFPrintf(fp, "  <%s>%s</%s>\n",
1195
 
                        pszName, pszValue, pszName);
 
1232
                AddIdent(fp, nIdentLevel);
 
1233
                poDS->PrintLine("<%s>%s</%s>", pszName, pszValue, pszName);
1196
1234
                CPLFree(pszValue);
1197
1235
            }
1198
1236
        }
1203
1241
    if (i < n)
1204
1242
    {
1205
1243
        const char* pszExtensionsNS = poDS->GetExtensionsNS();
1206
 
        VSIFPrintf(fp, "  <extensions>\n");
 
1244
        AddIdent(fp, nIdentLevel);
 
1245
        poDS->PrintLine("<extensions>");
1207
1246
        for(;i<n;i++)
1208
1247
        {
1209
1248
            OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( i );
1211
1250
            {
1212
1251
                char* compatibleName =
1213
1252
                        OGRGPX_GetXMLCompatibleTagName(pszExtensionsNS, poFieldDefn->GetNameRef());
1214
 
                const char *pszRaw = poFeature->GetFieldAsString( i );
1215
 
                
1216
 
                /* Try to detect XML content */
1217
 
                if (pszRaw[0] == '<' && pszRaw[strlen(pszRaw) - 1] == '>')
 
1253
 
 
1254
                if (poFieldDefn->GetType() == OFTReal)
1218
1255
                {
1219
 
                    if (OGRGPX_WriteXMLExtension(fp, compatibleName, pszRaw))
1220
 
                        continue;
 
1256
                    char szValue[64];
 
1257
                    OGRFormatDouble(szValue, sizeof(szValue), poFeature->GetFieldAsDouble(i), '.');
 
1258
                    AddIdent(fp, nIdentLevel + 1);
 
1259
                    poDS->PrintLine("<%s:%s>%s</%s:%s>",
 
1260
                                pszExtensionsNS,
 
1261
                                compatibleName,
 
1262
                                szValue,
 
1263
                                pszExtensionsNS,
 
1264
                                compatibleName);
1221
1265
                }
1222
 
                
1223
 
                /* Try to detect XML escaped content */
1224
 
                else if (strncmp(pszRaw, "&lt;", 4) == 0 &&
1225
 
                         strncmp(pszRaw + strlen(pszRaw) - 4, "&gt;", 4) == 0)
 
1266
                else
1226
1267
                {
1227
 
                    char* pszUnescapedContent = CPLUnescapeString( pszRaw, NULL, CPLES_XML );
1228
 
                    
1229
 
                    if (OGRGPX_WriteXMLExtension(fp, compatibleName, pszUnescapedContent))
1230
 
                    {
 
1268
                    const char *pszRaw = poFeature->GetFieldAsString( i );
 
1269
 
 
1270
                    /* Try to detect XML content */
 
1271
                    if (pszRaw[0] == '<' && pszRaw[strlen(pszRaw) - 1] == '>')
 
1272
                    {
 
1273
                        if (OGRGPX_WriteXMLExtension( compatibleName, pszRaw))
 
1274
                            continue;
 
1275
                    }
 
1276
 
 
1277
                    /* Try to detect XML escaped content */
 
1278
                    else if (strncmp(pszRaw, "&lt;", 4) == 0 &&
 
1279
                            strncmp(pszRaw + strlen(pszRaw) - 4, "&gt;", 4) == 0)
 
1280
                    {
 
1281
                        char* pszUnescapedContent = CPLUnescapeString( pszRaw, NULL, CPLES_XML );
 
1282
 
 
1283
                        if (OGRGPX_WriteXMLExtension(compatibleName, pszUnescapedContent))
 
1284
                        {
 
1285
                            CPLFree(pszUnescapedContent);
 
1286
                            continue;
 
1287
                        }
 
1288
 
1231
1289
                        CPLFree(pszUnescapedContent);
1232
 
                        continue;
1233
 
                    }
1234
 
                    
1235
 
                    CPLFree(pszUnescapedContent);
1236
 
                }
1237
 
 
1238
 
                /* Remove leading spaces for a numeric field */
1239
 
                if (poFieldDefn->GetType() == OFTInteger || poFieldDefn->GetType() == OFTReal)
1240
 
                {
1241
 
                    while( *pszRaw == ' ' )
1242
 
                        pszRaw++;
1243
 
                }
1244
 
 
1245
 
                char *pszEscaped = OGRGetXML_UTF8_EscapedString( pszRaw );
1246
 
                VSIFPrintf(fp, "    <%s:%s>%s</%s:%s>\n",
1247
 
                        pszExtensionsNS,
1248
 
                        compatibleName,
1249
 
                        pszEscaped,
1250
 
                        pszExtensionsNS,
1251
 
                        compatibleName);
 
1290
                    }
 
1291
 
 
1292
                    /* Remove leading spaces for a numeric field */
 
1293
                    if (poFieldDefn->GetType() == OFTInteger || poFieldDefn->GetType() == OFTReal)
 
1294
                    {
 
1295
                        while( *pszRaw == ' ' )
 
1296
                            pszRaw++;
 
1297
                    }
 
1298
 
 
1299
                    char *pszEscaped = OGRGetXML_UTF8_EscapedString( pszRaw );
 
1300
                    AddIdent(fp, nIdentLevel + 1);
 
1301
                    poDS->PrintLine("<%s:%s>%s</%s:%s>",
 
1302
                            pszExtensionsNS,
 
1303
                            compatibleName,
 
1304
                            pszEscaped,
 
1305
                            pszExtensionsNS,
 
1306
                            compatibleName);
 
1307
                    CPLFree(pszEscaped);
 
1308
                }
1252
1309
                CPLFree(compatibleName);
1253
 
                CPLFree(pszEscaped);
1254
1310
            }
1255
1311
        }
1256
 
        VSIFPrintf(fp, "  </extensions>\n");
 
1312
        AddIdent(fp, nIdentLevel);
 
1313
        poDS->PrintLine("</extensions>");
1257
1314
    }
1258
1315
}
1259
1316
 
1305
1362
OGRErr OGRGPXLayer::CreateFeature( OGRFeature *poFeature )
1306
1363
 
1307
1364
{
1308
 
    FILE* fp = poDS->GetOutputFP();
 
1365
    VSILFILE* fp = poDS->GetOutputFP();
1309
1366
    if (fp == NULL)
1310
1367
        return CE_Failure;
1311
1368
    
 
1369
    char szLat[64];
 
1370
    char szLon[64];
 
1371
    char szAlt[64];
 
1372
    
1312
1373
    OGRGeometry     *poGeom = poFeature->GetGeometryRef();
1313
1374
    
1314
1375
    if (gpxGeomType == GPX_WPT)
1329
1390
        
1330
1391
        poDS->SetLastGPXGeomTypeWritten(gpxGeomType);
1331
1392
 
1332
 
        if ( poGeom == NULL )
1333
 
        {
1334
 
            CPLError( CE_Failure, CPLE_AppDefined, 
1335
 
                      "Features without geometry not supported by GPX writer in waypoints layer." );
1336
 
            return OGRERR_FAILURE;
1337
 
        }
1338
 
 
1339
 
        switch( poGeom->getGeometryType() )
1340
 
        {
1341
 
            case wkbPoint:
1342
 
            case wkbPoint25D:
1343
 
            {
1344
 
                OGRPoint* point = (OGRPoint*)poGeom;
1345
 
                double lat = point->getY();
1346
 
                double lon = point->getX();
1347
 
                CheckAndFixCoordinatesValidity(&lat, &lon);
1348
 
                poDS->AddCoord(lon, lat);
1349
 
                VSIFPrintf(fp, "<wpt lat=\"%.15f\" lon=\"%.15f\">\n", lat, lon);
1350
 
                WriteFeatureAttributes(poFeature);
1351
 
                VSIFPrintf(fp, "</wpt>\n");
1352
 
                break;
1353
 
            }
1354
 
            
1355
 
            default:
1356
 
            {
1357
 
                CPLError( CE_Failure, CPLE_NotSupported,
1358
 
                    "Geometry type of `%s' not supported fort 'wpt' element.\n",
1359
 
                    OGRGeometryTypeToName(poGeom->getGeometryType()) );
1360
 
                return OGRERR_FAILURE;
1361
 
            }
1362
 
        }
 
1393
        if ( poGeom == NULL || wkbFlatten(poGeom->getGeometryType()) != wkbPoint )
 
1394
        {
 
1395
            CPLError( CE_Failure, CPLE_AppDefined, 
 
1396
                      "Features without geometry or with non-ponctual geometries not supported by GPX writer in waypoints layer." );
 
1397
            return OGRERR_FAILURE;
 
1398
        }
 
1399
 
 
1400
        if ( poGeom->getCoordinateDimension() == 0 )
 
1401
        {
 
1402
            CPLError( CE_Failure, CPLE_AppDefined, 
 
1403
                      "POINT EMPTY geometries not supported by GPX writer." );
 
1404
            return OGRERR_FAILURE;
 
1405
        }
 
1406
 
 
1407
        OGRPoint* point = (OGRPoint*)poGeom;
 
1408
        double lat = point->getY();
 
1409
        double lon = point->getX();
 
1410
        CheckAndFixCoordinatesValidity(&lat, &lon);
 
1411
        poDS->AddCoord(lon, lat);
 
1412
        OGRFormatDouble(szLat, sizeof(szLat), lat, '.');
 
1413
        OGRFormatDouble(szLon, sizeof(szLon), lon, '.');
 
1414
        poDS->PrintLine("<wpt lat=\"%s\" lon=\"%s\">", szLat, szLon);
 
1415
        WriteFeatureAttributes(poFeature);
 
1416
        poDS->PrintLine("</wpt>");
1363
1417
    }
1364
1418
    else if (gpxGeomType == GPX_ROUTE)
1365
1419
    {
1366
 
        if (poDS->GetLastGPXGeomTypeWritten() == GPX_TRACK)
 
1420
        if (poDS->GetLastGPXGeomTypeWritten() == GPX_TRACK ||
 
1421
            poDS->GetLastGPXGeomTypeWritten() == GPX_TRACK_POINT)
1367
1422
        {
1368
1423
            CPLError( CE_Failure, CPLE_NotSupported,
1369
1424
                        "Cannot write a 'rte' element after a 'trk' element.\n");
1370
1425
            return OGRERR_FAILURE;
1371
1426
        }
1372
 
        
 
1427
 
 
1428
        if (poDS->GetLastGPXGeomTypeWritten() == GPX_ROUTE_POINT && poDS->nLastRteId != -1)
 
1429
        {
 
1430
            poDS->PrintLine("</rte>");
 
1431
            poDS->nLastRteId = -1;
 
1432
        }
 
1433
 
1373
1434
        poDS->SetLastGPXGeomTypeWritten(gpxGeomType);
1374
1435
 
1375
1436
        OGRLineString* line = NULL;
1376
1437
 
1377
1438
        if ( poGeom == NULL )
1378
1439
        {
1379
 
            VSIFPrintf(fp, "<rte>\n");
 
1440
            poDS->PrintLine("<rte>");
1380
1441
            WriteFeatureAttributes(poFeature);
1381
 
            VSIFPrintf(fp, "</rte>\n");
 
1442
            poDS->PrintLine("</rte>");
1382
1443
            return OGRERR_NONE;
1383
1444
        }
1384
1445
 
1423
1484
 
1424
1485
        int n = (line) ? line->getNumPoints() : 0;
1425
1486
        int i;
1426
 
        VSIFPrintf(fp, "<rte>\n");
 
1487
        poDS->PrintLine("<rte>");
1427
1488
        WriteFeatureAttributes(poFeature);
1428
1489
        for(i=0;i<n;i++)
1429
1490
        {
1431
1492
            double lon = line->getX(i);
1432
1493
            CheckAndFixCoordinatesValidity(&lat, &lon);
1433
1494
            poDS->AddCoord(lon, lat);
1434
 
            VSIFPrintf(fp, "  <rtept lat=\"%.15f\" lon=\"%.15f\">\n", lat, lon);
 
1495
            OGRFormatDouble(szLat, sizeof(szLat), lat, '.');
 
1496
            OGRFormatDouble(szLon, sizeof(szLon), lon, '.');
 
1497
            poDS->PrintLine("  <rtept lat=\"%s\" lon=\"%s\">", szLat, szLon);
1435
1498
            if (poGeom->getGeometryType() == wkbLineString25D ||
1436
1499
                poGeom->getGeometryType() == wkbMultiLineString25D)
1437
1500
            {
1438
 
                VSIFPrintf(fp, "    <ele>%f</ele>\n", line->getZ(i));
 
1501
                OGRFormatDouble(szAlt, sizeof(szAlt), line->getZ(i), '.');
 
1502
                poDS->PrintLine("    <ele>%s</ele>", szAlt);
1439
1503
            }
1440
 
            VSIFPrintf(fp, "  </rtept>\n");
 
1504
            poDS->PrintLine("  </rtept>");
1441
1505
        }
1442
 
        VSIFPrintf(fp, "</rte>\n");
 
1506
        poDS->PrintLine("</rte>");
1443
1507
    }
1444
 
    else
 
1508
    else if (gpxGeomType == GPX_TRACK)
1445
1509
    {
 
1510
        if (poDS->GetLastGPXGeomTypeWritten() == GPX_ROUTE_POINT && poDS->nLastRteId != -1)
 
1511
        {
 
1512
            poDS->PrintLine("</rte>");
 
1513
            poDS->nLastRteId = -1;
 
1514
        }
 
1515
        if (poDS->GetLastGPXGeomTypeWritten() == GPX_TRACK_POINT && poDS->nLastTrkId != -1)
 
1516
        {
 
1517
            poDS->PrintLine("  </trkseg>");
 
1518
            poDS->PrintLine("</trk>");
 
1519
            poDS->nLastTrkId = -1;
 
1520
            poDS->nLastTrkSegId = -1;
 
1521
        }
 
1522
 
1446
1523
        poDS->SetLastGPXGeomTypeWritten(gpxGeomType);
1447
1524
 
1448
1525
        if (poGeom == NULL)
1449
1526
        {
1450
 
            VSIFPrintf(fp, "<trk>\n");
 
1527
            poDS->PrintLine("<trk>");
1451
1528
            WriteFeatureAttributes(poFeature);
1452
 
            VSIFPrintf(fp, "</trk>\n");
 
1529
            poDS->PrintLine("</trk>");
1453
1530
            return OGRERR_NONE;
1454
1531
        }
1455
1532
 
1461
1538
                OGRLineString* line = (OGRLineString*)poGeom;
1462
1539
                int n = line->getNumPoints();
1463
1540
                int i;
1464
 
                VSIFPrintf(fp, "<trk>\n");
 
1541
                poDS->PrintLine("<trk>");
1465
1542
                WriteFeatureAttributes(poFeature);
1466
 
                VSIFPrintf(fp, "  <trkseg>\n");
 
1543
                poDS->PrintLine("  <trkseg>");
1467
1544
                for(i=0;i<n;i++)
1468
1545
                {
1469
1546
                    double lat = line->getY(i);
1470
1547
                    double lon = line->getX(i);
1471
1548
                    CheckAndFixCoordinatesValidity(&lat, &lon);
1472
1549
                    poDS->AddCoord(lon, lat);
1473
 
                    VSIFPrintf(fp, "    <trkpt lat=\"%.15f\" lon=\"%.15f\">\n", lat, lon);
 
1550
                    OGRFormatDouble(szLat, sizeof(szLat), lat, '.');
 
1551
                    OGRFormatDouble(szLon, sizeof(szLon), lon, '.');
 
1552
                    poDS->PrintLine("    <trkpt lat=\"%s\" lon=\"%s\">", szLat, szLon);
1474
1553
                    if (line->getGeometryType() == wkbLineString25D)
1475
1554
                    {
1476
 
                        VSIFPrintf(fp, "        <ele>%f</ele>\n", line->getZ(i));
 
1555
                        OGRFormatDouble(szAlt, sizeof(szAlt), line->getZ(i), '.');
 
1556
                        poDS->PrintLine("        <ele>%s</ele>", szAlt);
1477
1557
                    }
1478
 
                    VSIFPrintf(fp, "    </trkpt>\n");
 
1558
                    poDS->PrintLine("    </trkpt>");
1479
1559
                }
1480
 
                VSIFPrintf(fp, "  </trkseg>\n");
1481
 
                VSIFPrintf(fp, "</trk>\n");
 
1560
                poDS->PrintLine("  </trkseg>");
 
1561
                poDS->PrintLine("</trk>");
1482
1562
                break;
1483
1563
            }
1484
1564
 
1486
1566
            case wkbMultiLineString25D:
1487
1567
            {
1488
1568
                int nGeometries = ((OGRGeometryCollection*)poGeom)->getNumGeometries ();
1489
 
                VSIFPrintf(fp, "<trk>\n");
 
1569
                poDS->PrintLine("<trk>");
1490
1570
                WriteFeatureAttributes(poFeature);
1491
1571
                int j;
1492
1572
                for(j=0;j<nGeometries;j++)
1494
1574
                    OGRLineString* line = (OGRLineString*) ( ((OGRGeometryCollection*)poGeom)->getGeometryRef(j) );
1495
1575
                    int n = (line) ? line->getNumPoints() : 0;
1496
1576
                    int i;
1497
 
                    VSIFPrintf(fp, "  <trkseg>\n");
 
1577
                    poDS->PrintLine("  <trkseg>");
1498
1578
                    for(i=0;i<n;i++)
1499
1579
                    {
1500
1580
                        double lat = line->getY(i);
1501
1581
                        double lon = line->getX(i);
1502
1582
                        CheckAndFixCoordinatesValidity(&lat, &lon);
1503
1583
                        poDS->AddCoord(lon, lat);
1504
 
                        VSIFPrintf(fp, "    <trkpt lat=\"%.15f\" lon=\"%.15f\">\n", lat, lon);
 
1584
                        OGRFormatDouble(szLat, sizeof(szLat), lat, '.');
 
1585
                        OGRFormatDouble(szLon, sizeof(szLon), lon, '.');
 
1586
                        poDS->PrintLine("    <trkpt lat=\"%s\" lon=\"%s\">", szLat, szLon);
1505
1587
                        if (line->getGeometryType() == wkbLineString25D)
1506
1588
                        {
1507
 
                            VSIFPrintf(fp, "        <ele>%f</ele>\n", line->getZ(i));
 
1589
                            OGRFormatDouble(szAlt, sizeof(szAlt), line->getZ(i), '.');
 
1590
                            poDS->PrintLine("        <ele>%s</ele>", szAlt);
1508
1591
                        }
1509
 
                        VSIFPrintf(fp, "    </trkpt>\n");
 
1592
                        poDS->PrintLine("    </trkpt>");
1510
1593
                    }
1511
 
                    VSIFPrintf(fp, "  </trkseg>\n");
 
1594
                    poDS->PrintLine("  </trkseg>");
1512
1595
                }
1513
 
                VSIFPrintf(fp, "</trk>\n");
 
1596
                poDS->PrintLine("</trk>");
1514
1597
                break;
1515
1598
            }
1516
1599
 
1523
1606
            }
1524
1607
        }
1525
1608
    }
 
1609
    else if (gpxGeomType == GPX_ROUTE_POINT)
 
1610
    {
 
1611
        if (poDS->GetLastGPXGeomTypeWritten() == GPX_TRACK ||
 
1612
            poDS->GetLastGPXGeomTypeWritten() == GPX_TRACK_POINT)
 
1613
        {
 
1614
            CPLError( CE_Failure, CPLE_NotSupported,
 
1615
                        "Cannot write a 'rte' element after a 'trk' element.\n");
 
1616
            return OGRERR_FAILURE;
 
1617
        }
 
1618
 
 
1619
        if ( poGeom == NULL || wkbFlatten(poGeom->getGeometryType()) != wkbPoint )
 
1620
        {
 
1621
            CPLError( CE_Failure, CPLE_AppDefined, 
 
1622
                      "Features without geometry or with non-ponctual geometries not supported by GPX writer in route_points layer." );
 
1623
            return OGRERR_FAILURE;
 
1624
        }
 
1625
 
 
1626
        if ( poGeom->getCoordinateDimension() == 0 )
 
1627
        {
 
1628
            CPLError( CE_Failure, CPLE_AppDefined, 
 
1629
                      "POINT EMPTY geometries not supported by GPX writer." );
 
1630
            return OGRERR_FAILURE;
 
1631
        }
 
1632
 
 
1633
        if ( !poFeature->IsFieldSet(FLD_ROUTE_FID) )
 
1634
        {
 
1635
            CPLError( CE_Failure, CPLE_AppDefined, 
 
1636
                      "Field %s must be set.", poFeatureDefn->GetFieldDefn(FLD_ROUTE_FID)->GetNameRef() );
 
1637
            return OGRERR_FAILURE;
 
1638
        }
 
1639
        if ( poFeature->GetFieldAsInteger(FLD_ROUTE_FID) < 0 )
 
1640
        {
 
1641
            CPLError( CE_Failure, CPLE_AppDefined, 
 
1642
                      "Invalid value for field %s.", poFeatureDefn->GetFieldDefn(FLD_ROUTE_FID)->GetNameRef() );
 
1643
            return OGRERR_FAILURE;
 
1644
        }
 
1645
 
 
1646
        poDS->SetLastGPXGeomTypeWritten(gpxGeomType);
 
1647
 
 
1648
        if ( poDS->nLastRteId != poFeature->GetFieldAsInteger(FLD_ROUTE_FID))
 
1649
        {
 
1650
            if (poDS->nLastRteId != -1)
 
1651
            {
 
1652
                poDS->PrintLine("</rte>");
 
1653
            }
 
1654
            poDS->PrintLine("<rte>");
 
1655
            if ( poFeature->IsFieldSet(FLD_ROUTE_NAME) )
 
1656
            {
 
1657
                char* pszValue =
 
1658
                            OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( FLD_ROUTE_NAME ));
 
1659
                poDS->PrintLine("  <%s>%s</%s>",
 
1660
                        "name", pszValue, "name");
 
1661
                CPLFree(pszValue);
 
1662
            }
 
1663
        }
 
1664
 
 
1665
        poDS->nLastRteId = poFeature->GetFieldAsInteger(FLD_ROUTE_FID);
 
1666
 
 
1667
        OGRPoint* point = (OGRPoint*)poGeom;
 
1668
        double lat = point->getY();
 
1669
        double lon = point->getX();
 
1670
        CheckAndFixCoordinatesValidity(&lat, &lon);
 
1671
        poDS->AddCoord(lon, lat);
 
1672
        OGRFormatDouble(szLat, sizeof(szLat), lat, '.');
 
1673
        OGRFormatDouble(szLon, sizeof(szLon), lon, '.');
 
1674
        poDS->PrintLine("  <rtept lat=\"%s\" lon=\"%s\">", szLat, szLon);
 
1675
        WriteFeatureAttributes(poFeature, 2);
 
1676
        poDS->PrintLine("  </rtept>");
 
1677
 
 
1678
    }
 
1679
    else
 
1680
    {
 
1681
        if (poDS->GetLastGPXGeomTypeWritten() == GPX_ROUTE_POINT && poDS->nLastRteId != -1)
 
1682
        {
 
1683
            poDS->PrintLine("</rte>");
 
1684
            poDS->nLastRteId = -1;
 
1685
        }
 
1686
 
 
1687
        if ( poGeom == NULL || wkbFlatten(poGeom->getGeometryType()) != wkbPoint )
 
1688
        {
 
1689
            CPLError( CE_Failure, CPLE_AppDefined, 
 
1690
                      "Features without geometry or with non-ponctual geometries not supported by GPX writer in track_points layer." );
 
1691
            return OGRERR_FAILURE;
 
1692
        }
 
1693
 
 
1694
        if ( poGeom->getCoordinateDimension() == 0 )
 
1695
        {
 
1696
            CPLError( CE_Failure, CPLE_AppDefined, 
 
1697
                      "POINT EMPTY geometries not supported by GPX writer." );
 
1698
            return OGRERR_FAILURE;
 
1699
        }
 
1700
 
 
1701
        if ( !poFeature->IsFieldSet(FLD_TRACK_FID) )
 
1702
        {
 
1703
            CPLError( CE_Failure, CPLE_AppDefined, 
 
1704
                      "Field %s must be set.", poFeatureDefn->GetFieldDefn(FLD_TRACK_FID)->GetNameRef() );
 
1705
            return OGRERR_FAILURE;
 
1706
        }
 
1707
        if ( poFeature->GetFieldAsInteger(FLD_TRACK_FID) < 0 )
 
1708
        {
 
1709
            CPLError( CE_Failure, CPLE_AppDefined, 
 
1710
                      "Invalid value for field %s.", poFeatureDefn->GetFieldDefn(FLD_TRACK_FID)->GetNameRef() );
 
1711
            return OGRERR_FAILURE;
 
1712
        }
 
1713
        if ( !poFeature->IsFieldSet(FLD_TRACK_SEG_ID) )
 
1714
        {
 
1715
            CPLError( CE_Failure, CPLE_AppDefined, 
 
1716
                      "Field %s must be set.", poFeatureDefn->GetFieldDefn(FLD_TRACK_SEG_ID)->GetNameRef() );
 
1717
            return OGRERR_FAILURE;
 
1718
        }
 
1719
        if ( poFeature->GetFieldAsInteger(FLD_TRACK_SEG_ID) < 0 )
 
1720
        {
 
1721
            CPLError( CE_Failure, CPLE_AppDefined, 
 
1722
                      "Invalid value for field %s.", poFeatureDefn->GetFieldDefn(FLD_TRACK_SEG_ID)->GetNameRef() );
 
1723
            return OGRERR_FAILURE;
 
1724
        }
 
1725
 
 
1726
        poDS->SetLastGPXGeomTypeWritten(gpxGeomType);
 
1727
 
 
1728
        if ( poDS->nLastTrkId != poFeature->GetFieldAsInteger(FLD_TRACK_FID))
 
1729
        {
 
1730
            if (poDS->nLastTrkId != -1)
 
1731
            {
 
1732
                poDS->PrintLine("  </trkseg>");
 
1733
                poDS->PrintLine("</trk>");
 
1734
            }
 
1735
            poDS->PrintLine("<trk>");
 
1736
 
 
1737
            if ( poFeature->IsFieldSet(FLD_TRACK_NAME) )
 
1738
            {
 
1739
                char* pszValue =
 
1740
                            OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( FLD_TRACK_NAME ));
 
1741
                poDS->PrintLine("  <%s>%s</%s>",
 
1742
                        "name", pszValue, "name");
 
1743
                CPLFree(pszValue);
 
1744
            }
 
1745
 
 
1746
            poDS->PrintLine("  <trkseg>");
 
1747
        }
 
1748
        else if (poDS->nLastTrkSegId != poFeature->GetFieldAsInteger(FLD_TRACK_SEG_ID))
 
1749
        {
 
1750
            poDS->PrintLine("  </trkseg>");
 
1751
            poDS->PrintLine("  <trkseg>");
 
1752
        }
 
1753
 
 
1754
        poDS->nLastTrkId = poFeature->GetFieldAsInteger(FLD_TRACK_FID);
 
1755
        poDS->nLastTrkSegId = poFeature->GetFieldAsInteger(FLD_TRACK_SEG_ID);
 
1756
 
 
1757
        OGRPoint* point = (OGRPoint*)poGeom;
 
1758
        double lat = point->getY();
 
1759
        double lon = point->getX();
 
1760
        CheckAndFixCoordinatesValidity(&lat, &lon);
 
1761
        poDS->AddCoord(lon, lat);
 
1762
        OGRFormatDouble(szLat, sizeof(szLat), lat, '.');
 
1763
        OGRFormatDouble(szLon, sizeof(szLon), lon, '.');
 
1764
        poDS->PrintLine("    <trkpt lat=\"%s\" lon=\"%s\">", szLat, szLon);
 
1765
        WriteFeatureAttributes(poFeature, 3);
 
1766
        poDS->PrintLine("    </trkpt>");
 
1767
    }
1526
1768
 
1527
1769
    return OGRERR_NONE;
1528
1770
}