LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/libkml - ogrlibkmlfield.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 556 266 47.8 %
Date: 2012-12-26 Functions: 14 10 71.4 %

       1                 : /******************************************************************************
       2                 :  *
       3                 :  * Project:  KML Translator
       4                 :  * Purpose:  Implements OGRLIBKMLDriver
       5                 :  * Author:   Brian Case, rush at winkey dot org
       6                 :  *
       7                 :  ******************************************************************************
       8                 :  * Copyright (c) 2010, Brian Case
       9                 :  *
      10                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      11                 :  * copy of this software and associated documentation files (the "Software"),
      12                 :  * to deal in the Software without restriction, including without limitation
      13                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14                 :  * and/or sell copies of the Software, and to permit persons to whom the
      15                 :  * Software is furnished to do so, subject to the following conditions:
      16                 :  *
      17                 :  * The above copyright notice and this permission notice shall be included
      18                 :  * in all copies or substantial portions of the Software.
      19                 :  *
      20                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26                 :  * DEALINGS IN THE SOFTWARE.
      27                 :  *****************************************************************************/
      28                 : 
      29                 : #include  <ogrsf_frmts.h>
      30                 : #include <ogr_feature.h>
      31                 : #include "ogr_p.h"
      32                 : 
      33                 : #include <kml/dom.h>
      34                 : #include <iostream>
      35                 : 
      36                 : using kmldom::ExtendedDataPtr;
      37                 : using kmldom::SchemaPtr;
      38                 : using kmldom::SchemaDataPtr;
      39                 : using kmldom::SimpleDataPtr;
      40                 : using kmldom::DataPtr;
      41                 : 
      42                 : using kmldom::TimeStampPtr;
      43                 : using kmldom::TimeSpanPtr;
      44                 : using kmldom::TimePrimitivePtr;
      45                 : 
      46                 : using kmldom::PointPtr;
      47                 : using kmldom::LineStringPtr;
      48                 : using kmldom::PolygonPtr;
      49                 : using kmldom::MultiGeometryPtr;
      50                 : using kmldom::GeometryPtr;
      51                 : 
      52                 : using kmldom::FeaturePtr;
      53                 : using kmldom::GroundOverlayPtr;
      54                 : using kmldom::IconPtr;
      55                 : 
      56                 : #include "ogr_libkml.h"
      57                 : 
      58                 : #include "ogrlibkmlfield.h"
      59                 : 
      60               0 : void ogr2altitudemode_rec (
      61                 :     GeometryPtr poKmlGeometry,
      62                 :     int iAltitudeMode,
      63                 :     int isGX )
      64                 : {
      65                 : 
      66               0 :     PointPtr poKmlPoint;
      67               0 :     LineStringPtr poKmlLineString;
      68               0 :     PolygonPtr poKmlPolygon;
      69               0 :     MultiGeometryPtr poKmlMultiGeometry;
      70                 : 
      71                 :     size_t nGeom;
      72                 :     size_t i;
      73                 : 
      74               0 :     switch ( poKmlGeometry->Type (  ) ) {
      75                 : 
      76                 :     case kmldom::Type_Point:
      77               0 :         poKmlPoint = AsPoint ( poKmlGeometry );
      78                 : 
      79               0 :         if ( !isGX )
      80               0 :             poKmlPoint->set_altitudemode ( iAltitudeMode );
      81                 :         else
      82               0 :             poKmlPoint->set_gx_altitudemode ( iAltitudeMode );
      83                 : 
      84               0 :         break;
      85                 : 
      86                 :     case kmldom::Type_LineString:
      87               0 :         poKmlLineString = AsLineString ( poKmlGeometry );
      88                 : 
      89               0 :         if ( !isGX )
      90               0 :             poKmlLineString->set_altitudemode ( iAltitudeMode );
      91                 :         else
      92               0 :             poKmlLineString->set_gx_altitudemode ( iAltitudeMode );
      93                 : 
      94               0 :         break;
      95                 : 
      96                 :     case kmldom::Type_LinearRing:
      97               0 :         break;
      98                 : 
      99                 :     case kmldom::Type_Polygon:
     100               0 :         poKmlPolygon = AsPolygon ( poKmlGeometry );
     101                 : 
     102               0 :         if ( !isGX )
     103               0 :             poKmlPolygon->set_altitudemode ( iAltitudeMode );
     104                 :         else
     105               0 :             poKmlPolygon->set_gx_altitudemode ( iAltitudeMode );
     106                 : 
     107               0 :         break;
     108                 : 
     109                 :     case kmldom::Type_MultiGeometry:
     110               0 :         poKmlMultiGeometry = AsMultiGeometry ( poKmlGeometry );
     111                 : 
     112               0 :         nGeom = poKmlMultiGeometry->get_geometry_array_size (  );
     113               0 :         for ( i = 0; i < nGeom; i++ ) {
     114                 :             ogr2altitudemode_rec ( poKmlMultiGeometry->
     115                 :                                    get_geometry_array_at ( i ), iAltitudeMode,
     116               0 :                                    isGX );
     117                 :         }
     118                 : 
     119                 :         break;
     120                 : 
     121                 :     default:
     122                 :         break;
     123                 : 
     124               0 :     }
     125                 : 
     126               0 : }
     127                 : 
     128               0 : void ogr2extrude_rec (
     129                 :     int nExtrude,
     130                 :     GeometryPtr poKmlGeometry )
     131                 : {
     132                 : 
     133               0 :     PointPtr poKmlPoint;
     134               0 :     LineStringPtr poKmlLineString;
     135               0 :     PolygonPtr poKmlPolygon;
     136               0 :     MultiGeometryPtr poKmlMultiGeometry;
     137                 : 
     138                 :     size_t nGeom;
     139                 :     size_t i;
     140                 : 
     141               0 :     switch ( poKmlGeometry->Type (  ) ) {
     142                 :     case kmldom::Type_Point:
     143               0 :         poKmlPoint = AsPoint ( poKmlGeometry );
     144               0 :         poKmlPoint->set_extrude ( nExtrude );
     145               0 :         break;
     146                 : 
     147                 :     case kmldom::Type_LineString:
     148               0 :         poKmlLineString = AsLineString ( poKmlGeometry );
     149               0 :         poKmlLineString->set_extrude ( nExtrude );
     150               0 :         break;
     151                 : 
     152                 :     case kmldom::Type_LinearRing:
     153               0 :         break;
     154                 : 
     155                 :     case kmldom::Type_Polygon:
     156               0 :         poKmlPolygon = AsPolygon ( poKmlGeometry );
     157               0 :         poKmlPolygon->set_extrude ( nExtrude );
     158               0 :         break;
     159                 : 
     160                 :     case kmldom::Type_MultiGeometry:
     161               0 :         poKmlMultiGeometry = AsMultiGeometry ( poKmlGeometry );
     162                 : 
     163               0 :         nGeom = poKmlMultiGeometry->get_geometry_array_size (  );
     164               0 :         for ( i = 0; i < nGeom; i++ ) {
     165                 :             ogr2extrude_rec ( nExtrude,
     166                 :                               poKmlMultiGeometry->
     167               0 :                               get_geometry_array_at ( i ) );
     168                 :         }
     169                 :         break;
     170                 : 
     171                 :     default:
     172                 :         break;
     173                 : 
     174               0 :     }
     175               0 : }
     176                 : 
     177               0 : void ogr2tessellate_rec (
     178                 :     int nTessellate,
     179                 :     GeometryPtr poKmlGeometry )
     180                 : {
     181                 : 
     182               0 :     LineStringPtr poKmlLineString;
     183               0 :     PolygonPtr poKmlPolygon;
     184               0 :     MultiGeometryPtr poKmlMultiGeometry;
     185                 : 
     186                 :     size_t nGeom;
     187                 :     size_t i;
     188                 : 
     189               0 :     switch ( poKmlGeometry->Type (  ) ) {
     190                 : 
     191                 :     case kmldom::Type_Point:
     192               0 :         break;
     193                 : 
     194                 :     case kmldom::Type_LineString:
     195               0 :         poKmlLineString = AsLineString ( poKmlGeometry );
     196               0 :         poKmlLineString->set_tessellate ( nTessellate );
     197               0 :         break;
     198                 : 
     199                 :     case kmldom::Type_LinearRing:
     200               0 :         break;
     201                 : 
     202                 :     case kmldom::Type_Polygon:
     203               0 :         poKmlPolygon = AsPolygon ( poKmlGeometry );
     204                 : 
     205               0 :         poKmlPolygon->set_tessellate ( nTessellate );
     206               0 :         break;
     207                 : 
     208                 :     case kmldom::Type_MultiGeometry:
     209               0 :         poKmlMultiGeometry = AsMultiGeometry ( poKmlGeometry );
     210                 : 
     211               0 :         nGeom = poKmlMultiGeometry->get_geometry_array_size (  );
     212               0 :         for ( i = 0; i < nGeom; i++ ) {
     213                 :             ogr2tessellate_rec ( nTessellate,
     214                 :                                  poKmlMultiGeometry->
     215               0 :                                  get_geometry_array_at ( i ) );
     216                 :         }
     217                 : 
     218                 :         break;
     219                 : 
     220                 :     default:
     221                 :         break;
     222                 : 
     223               0 :     }
     224               0 : }
     225                 : 
     226                 : 
     227                 : /************************************************************************/
     228                 : /*                 OGRLIBKMLSanitizeUTF8String()                        */
     229                 : /************************************************************************/
     230                 : 
     231               9 : static char* OGRLIBKMLSanitizeUTF8String(const char* pszString)
     232                 : {
     233               9 :     if (!CPLIsUTF8(pszString, -1) &&
     234                 :          CSLTestBoolean(CPLGetConfigOption("OGR_FORCE_ASCII", "YES")))
     235                 :     {
     236                 :         static int bFirstTime = TRUE;
     237               0 :         if (bFirstTime)
     238                 :         {
     239               0 :             bFirstTime = FALSE;
     240                 :             CPLError(CE_Warning, CPLE_AppDefined,
     241                 :                     "%s is not a valid UTF-8 string. Forcing it to ASCII.\n"
     242                 :                     "If you still want the original string and change the XML file encoding\n"
     243                 :                     "afterwards, you can define OGR_FORCE_ASCII=NO as configuration option.\n"
     244               0 :                     "This warning won't be issued anymore", pszString);
     245                 :         }
     246                 :         else
     247                 :         {
     248                 :             CPLDebug("OGR", "%s is not a valid UTF-8 string. Forcing it to ASCII",
     249               0 :                     pszString);
     250                 :         }
     251               0 :         return CPLForceToASCII(pszString, -1, '?');
     252                 :     }
     253                 :     else
     254               9 :         return CPLStrdup(pszString);
     255                 : }
     256                 : 
     257                 : /******************************************************************************
     258                 :  function to output ogr fields in kml
     259                 : 
     260                 :  args:
     261                 :         poOgrFeat       pointer to the feature the field is in
     262                 :         poOgrLayer      pointer to the layer the feature is in
     263                 :         poKmlFactory    pointer to the libkml dom factory
     264                 :         poKmlPlacemark  pointer to the placemark to add to
     265                 :  
     266                 :  returns:
     267                 :         nothing
     268                 : 
     269                 :  env vars:
     270                 :   LIBKML_TIMESTAMP_FIELD         default: OFTDate or OFTDateTime named timestamp
     271                 :   LIBKML_TIMESPAN_BEGIN_FIELD    default: OFTDate or OFTDateTime named begin
     272                 :   LIBKML_TIMESPAN_END_FIELD      default: OFTDate or OFTDateTime named end
     273                 :   LIBKML_DESCRIPTION_FIELD       default: none
     274                 :   LIBKML_NAME_FIELD              default: OFTString field named name
     275                 : 
     276                 : 
     277                 : ******************************************************************************/
     278                 : 
     279                 : 
     280                 : 
     281              27 : void field2kml (
     282                 :     OGRFeature * poOgrFeat,
     283                 :     OGRLIBKMLLayer * poOgrLayer,
     284                 :     KmlFactory * poKmlFactory,
     285                 :     PlacemarkPtr poKmlPlacemark )
     286                 : {
     287                 :     int i;
     288                 : 
     289              27 :     SchemaDataPtr poKmlSchemaData = poKmlFactory->CreateSchemaData (  );
     290              27 :     SchemaPtr poKmlSchema = poOgrLayer->GetKmlSchema (  );
     291                 : 
     292                 :     /***** set the url to the schema *****/
     293                 : 
     294              27 :     if ( poKmlSchema && poKmlSchema->has_id (  ) ) {
     295              27 :         std::string oKmlSchemaID = poKmlSchema->get_id (  );
     296                 : 
     297                 : 
     298              27 :         std::string oKmlSchemaURL = "#";
     299              27 :         oKmlSchemaURL.append ( oKmlSchemaID );
     300                 : 
     301              27 :         poKmlSchemaData->set_schemaurl ( oKmlSchemaURL );
     302                 :     }
     303                 : 
     304              27 :     const char *namefield = CPLGetConfigOption ( "LIBKML_NAME_FIELD", "Name" );
     305                 :     const char *descfield =
     306              27 :         CPLGetConfigOption ( "LIBKML_DESCRIPTION_FIELD", "description" );
     307                 :     const char *tsfield =
     308              27 :         CPLGetConfigOption ( "LIBKML_TIMESTAMP_FIELD", "timestamp" );
     309                 :     const char *beginfield =
     310              27 :         CPLGetConfigOption ( "LIBKML_BEGIN_FIELD", "begin" );
     311              27 :     const char *endfield = CPLGetConfigOption ( "LIBKML_END_FIELD", "end" );
     312                 :     const char *altitudeModefield =
     313              27 :         CPLGetConfigOption ( "LIBKML_ALTITUDEMODE_FIELD", "altitudeMode" );
     314                 :     const char *tessellatefield =
     315              27 :         CPLGetConfigOption ( "LIBKML_TESSELLATE_FIELD", "tessellate" );
     316                 :     const char *extrudefield =
     317              27 :         CPLGetConfigOption ( "LIBKML_EXTRUDE_FIELD", "extrude" );
     318                 :     const char *visibilityfield =
     319              27 :         CPLGetConfigOption ( "LIBKML_VISIBILITY_FIELD", "visibility" );
     320                 : 
     321              27 :     TimeSpanPtr poKmlTimeSpan = NULL;
     322                 : 
     323              27 :     int nFields = poOgrFeat->GetFieldCount (  );
     324              27 :     int iSkip1 = -1;
     325              27 :     int iSkip2 = -1;
     326                 : 
     327              27 :     for ( i = 0; i < nFields; i++ ) {
     328                 : 
     329                 :         /***** if the field is set to skip, do so *****/
     330                 : 
     331              72 :         if ( i == iSkip1 || i == iSkip2 )
     332               0 :             continue;
     333                 : 
     334                 :         /***** if the field isn't set just bail now *****/
     335                 : 
     336              72 :         if ( !poOgrFeat->IsFieldSet ( i ) )
     337              63 :             continue;
     338                 : 
     339               9 :         OGRFieldDefn *poOgrFieldDef = poOgrFeat->GetFieldDefnRef ( i );
     340               9 :         OGRFieldType type = poOgrFieldDef->GetType (  );
     341               9 :         const char *name = poOgrFieldDef->GetNameRef (  );
     342                 : 
     343               9 :         SimpleDataPtr poKmlSimpleData = NULL;
     344                 :         int year,
     345                 :             month,
     346                 :             day,
     347                 :             hour,
     348                 :             min,
     349                 :             sec,
     350                 :             tz;
     351                 : 
     352               9 :         switch ( type ) {
     353                 : 
     354                 :         case OFTString:        //     String of ASCII chars
     355                 :             {
     356                 :                 char* pszUTF8String = OGRLIBKMLSanitizeUTF8String(
     357               9 :                                         poOgrFeat->GetFieldAsString ( i ));
     358                 :                 /***** name *****/
     359                 : 
     360               9 :                 if ( EQUAL ( name, namefield ) ) {
     361               3 :                     poKmlPlacemark->set_name ( pszUTF8String );
     362               3 :                     CPLFree( pszUTF8String );
     363               3 :                     continue;
     364                 :                 }
     365                 : 
     366                 :                 /***** description *****/
     367                 : 
     368               6 :                 else if ( EQUAL ( name, descfield ) ) {
     369               3 :                     poKmlPlacemark->set_description ( pszUTF8String );
     370               3 :                     CPLFree( pszUTF8String );
     371               3 :                     continue;
     372                 :                 }
     373                 : 
     374                 :                 /***** altitudemode *****/
     375                 : 
     376               3 :                 else if ( EQUAL ( name, altitudeModefield ) ) {
     377               0 :                     const char *pszAltitudeMode = pszUTF8String ;
     378                 : 
     379               0 :                     int isGX = FALSE;
     380               0 :                     int iAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND;
     381                 : 
     382               0 :                     if ( EQUAL ( pszAltitudeMode, "clampToGround" ) )
     383               0 :                         iAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND;
     384                 : 
     385               0 :                     else if ( EQUAL ( pszAltitudeMode, "relativeToGround" ) )
     386               0 :                         iAltitudeMode = kmldom::ALTITUDEMODE_RELATIVETOGROUND;
     387                 : 
     388               0 :                     else if ( EQUAL ( pszAltitudeMode, "absolute" ) )
     389               0 :                         iAltitudeMode = kmldom::ALTITUDEMODE_ABSOLUTE;
     390                 : 
     391               0 :                     else if ( EQUAL ( pszAltitudeMode, "relativeToSeaFloor" ) ) {
     392                 :                         iAltitudeMode =
     393               0 :                             kmldom::GX_ALTITUDEMODE_RELATIVETOSEAFLOOR;
     394               0 :                         isGX = TRUE;
     395                 :                     }
     396                 : 
     397               0 :                     else if ( EQUAL ( pszAltitudeMode, "clampToSeaFloor" ) ) {
     398                 :                         iAltitudeMode =
     399               0 :                             kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR;
     400               0 :                         isGX = TRUE;
     401                 :                     }
     402                 : 
     403                 : 
     404               0 :                     if ( poKmlPlacemark->has_geometry (  ) ) {
     405                 :                         GeometryPtr poKmlGeometry =
     406               0 :                             poKmlPlacemark->get_geometry (  );
     407                 : 
     408                 :                         ogr2altitudemode_rec ( poKmlGeometry, iAltitudeMode,
     409               0 :                                                isGX );
     410                 : 
     411                 :                     }
     412                 : 
     413               0 :                     CPLFree( pszUTF8String );
     414                 : 
     415               0 :                     continue;
     416                 :                 }
     417                 :                 
     418                 :                 /***** timestamp *****/
     419                 : 
     420               3 :                 else if ( EQUAL ( name, tsfield ) ) {
     421                 : 
     422                 :                     TimeStampPtr poKmlTimeStamp =
     423               0 :                         poKmlFactory->CreateTimeStamp (  );
     424               0 :                     poKmlTimeStamp->set_when ( pszUTF8String  );
     425               0 :                     poKmlPlacemark->set_timeprimitive ( poKmlTimeStamp );
     426                 : 
     427               0 :                     CPLFree( pszUTF8String );
     428                 : 
     429               0 :                     continue;
     430                 :                 }
     431                 : 
     432                 :                 /***** begin *****/
     433                 : 
     434               3 :                 if ( EQUAL ( name, beginfield ) ) {
     435                 : 
     436               0 :                     if ( !poKmlTimeSpan ) {
     437               0 :                         poKmlTimeSpan = poKmlFactory->CreateTimeSpan (  );
     438               0 :                         poKmlPlacemark->set_timeprimitive ( poKmlTimeSpan );
     439                 :                     }
     440                 : 
     441               0 :                     poKmlTimeSpan->set_begin ( pszUTF8String );
     442                 : 
     443               0 :                     CPLFree( pszUTF8String );
     444                 : 
     445               0 :                     continue;
     446                 : 
     447                 :                 }
     448                 : 
     449                 :                 /***** end *****/
     450                 : 
     451               3 :                 else if ( EQUAL ( name, endfield ) ) {
     452                 : 
     453               0 :                     if ( !poKmlTimeSpan ) {
     454               0 :                         poKmlTimeSpan = poKmlFactory->CreateTimeSpan (  );
     455               0 :                         poKmlPlacemark->set_timeprimitive ( poKmlTimeSpan );
     456                 :                     }
     457                 : 
     458               0 :                     poKmlTimeSpan->set_end ( pszUTF8String );
     459                 : 
     460               0 :                     CPLFree( pszUTF8String );
     461                 : 
     462               0 :                     continue;
     463                 :                 }
     464                 :                 
     465                 :                 /***** other *****/
     466                 : 
     467               3 :                 poKmlSimpleData = poKmlFactory->CreateSimpleData (  );
     468               3 :                 poKmlSimpleData->set_name ( name );
     469               6 :                 poKmlSimpleData->set_text ( pszUTF8String );
     470                 : 
     471               3 :                 CPLFree( pszUTF8String );
     472                 : 
     473               3 :                 break;
     474                 :             }
     475                 : 
     476                 :         case OFTDate:          //   Date
     477                 :             {
     478                 :                 poOgrFeat->GetFieldAsDateTime ( i, &year, &month, &day,
     479               0 :                                                 &hour, &min, &sec, &tz );
     480                 : 
     481                 :                 int iTimeField;
     482                 : 
     483               0 :                 for ( iTimeField = i + 1; iTimeField < nFields; iTimeField++ ) {
     484               0 :                     if ( iTimeField == iSkip1 || iTimeField == iSkip2 )
     485               0 :                         continue;
     486                 : 
     487                 :                     OGRFieldDefn *poOgrFieldDef2 =
     488               0 :                         poOgrFeat->GetFieldDefnRef ( i );
     489               0 :                     OGRFieldType type2 = poOgrFieldDef2->GetType (  );
     490               0 :                     const char *name2 = poOgrFieldDef2->GetNameRef (  );
     491                 : 
     492               0 :                     if ( EQUAL ( name2, name ) && type2 == OFTTime &&
     493                 :                          ( EQUAL ( name, tsfield ) ||
     494                 :                            EQUAL ( name, beginfield ) ||
     495                 :                            EQUAL ( name, endfield ) ) ) {
     496                 : 
     497                 :                         int year2,
     498                 :                             month2,
     499                 :                             day2,
     500                 :                             hour2,
     501                 :                             min2,
     502                 :                             sec2,
     503                 :                             tz2;
     504                 : 
     505                 :                         poOgrFeat->GetFieldAsDateTime ( iTimeField, &year2,
     506                 :                                                         &month2, &day2, &hour2,
     507               0 :                                                         &min2, &sec2, &tz2 );
     508                 : 
     509               0 :                         hour = hour2;
     510               0 :                         min = min2;
     511               0 :                         sec = sec2;
     512               0 :                         tz = tz2;
     513                 : 
     514               0 :                         if ( 0 > iSkip1 )
     515               0 :                             iSkip1 = iTimeField;
     516                 :                         else
     517               0 :                             iSkip2 = iTimeField;
     518                 :                     }
     519                 :                 }
     520                 : 
     521               0 :                 goto Do_DateTime;
     522                 : 
     523                 :             }
     524                 : 
     525                 : 
     526                 :         case OFTTime:          //   Time
     527                 :             {
     528                 :                 poOgrFeat->GetFieldAsDateTime ( i, &year, &month, &day,
     529               0 :                                                 &hour, &min, &sec, &tz );
     530                 : 
     531                 :                 int iTimeField;
     532                 : 
     533               0 :                 for ( iTimeField = i + 1; iTimeField < nFields; iTimeField++ ) {
     534               0 :                     if ( iTimeField == iSkip1 || iTimeField == iSkip2 )
     535               0 :                         continue;
     536                 : 
     537                 :                     OGRFieldDefn *poOgrFieldDef2 =
     538               0 :                         poOgrFeat->GetFieldDefnRef ( i );
     539               0 :                     OGRFieldType type2 = poOgrFieldDef2->GetType (  );
     540               0 :                     const char *name2 = poOgrFieldDef2->GetNameRef (  );
     541                 : 
     542               0 :                     if ( EQUAL ( name2, name ) && type2 == OFTTime &&
     543                 :                          ( EQUAL ( name, tsfield ) ||
     544                 :                            EQUAL ( name, beginfield ) ||
     545                 :                            EQUAL ( name, endfield ) ) ) {
     546                 : 
     547                 :                         int year2,
     548                 :                             month2,
     549                 :                             day2,
     550                 :                             hour2,
     551                 :                             min2,
     552                 :                             sec2,
     553                 :                             tz2;
     554                 : 
     555                 :                         poOgrFeat->GetFieldAsDateTime ( iTimeField, &year2,
     556                 :                                                         &month2, &day2, &hour2,
     557               0 :                                                         &min2, &sec2, &tz2 );
     558                 : 
     559               0 :                         year = year2;
     560               0 :                         month = month2;
     561               0 :                         day = day2;
     562                 : 
     563               0 :                         if ( 0 > iSkip1 )
     564               0 :                             iSkip1 = iTimeField;
     565                 :                         else
     566               0 :                             iSkip2 = iTimeField;
     567                 :                     }
     568                 :                 }
     569                 : 
     570               0 :                 goto Do_DateTime;
     571                 : 
     572                 :             }
     573                 : 
     574                 :         case OFTDateTime:      //  Date and Time
     575                 :             {
     576                 :                 poOgrFeat->GetFieldAsDateTime ( i, &year, &month, &day,
     577               0 :                                                 &hour, &min, &sec, &tz );
     578                 : 
     579                 :               Do_DateTime:
     580                 :                 /***** timestamp *****/
     581                 : 
     582               0 :                 if ( EQUAL ( name, tsfield ) ) {
     583                 : 
     584                 :                     char *timebuf = OGRGetXMLDateTime ( year, month, day, hour,
     585               0 :                                                         min, sec, tz );
     586                 : 
     587                 :                     TimeStampPtr poKmlTimeStamp =
     588               0 :                         poKmlFactory->CreateTimeStamp (  );
     589               0 :                     poKmlTimeStamp->set_when ( timebuf );
     590               0 :                     poKmlPlacemark->set_timeprimitive ( poKmlTimeStamp );
     591               0 :                     CPLFree( timebuf );
     592                 : 
     593               0 :                     continue;
     594                 :                 }
     595                 : 
     596                 :                 /***** begin *****/
     597                 : 
     598               0 :                 if ( EQUAL ( name, beginfield ) ) {
     599                 : 
     600                 :                     char *timebuf = OGRGetXMLDateTime ( year, month, day, hour,
     601               0 :                                                         min, sec, tz );
     602                 : 
     603               0 :                     if ( !poKmlTimeSpan ) {
     604               0 :                         poKmlTimeSpan = poKmlFactory->CreateTimeSpan (  );
     605               0 :                         poKmlPlacemark->set_timeprimitive ( poKmlTimeSpan );
     606                 :                     }
     607                 : 
     608               0 :                     poKmlTimeSpan->set_begin ( timebuf );
     609               0 :                     CPLFree( timebuf );
     610                 : 
     611               0 :                     continue;
     612                 : 
     613                 :                 }
     614                 : 
     615                 :                 /***** end *****/
     616                 : 
     617               0 :                 else if ( EQUAL ( name, endfield ) ) {
     618                 : 
     619                 :                     char *timebuf = OGRGetXMLDateTime ( year, month, day, hour,
     620               0 :                                                         min, sec, tz );
     621                 : 
     622                 : 
     623               0 :                     if ( !poKmlTimeSpan ) {
     624               0 :                         poKmlTimeSpan = poKmlFactory->CreateTimeSpan (  );
     625               0 :                         poKmlPlacemark->set_timeprimitive ( poKmlTimeSpan );
     626                 :                     }
     627                 : 
     628               0 :                     poKmlTimeSpan->set_end ( timebuf );
     629               0 :                     CPLFree( timebuf );
     630                 : 
     631               0 :                     continue;
     632                 :                 }
     633                 : 
     634                 :                 /***** other *****/
     635                 : 
     636               0 :                 poKmlSimpleData = poKmlFactory->CreateSimpleData (  );
     637               0 :                 poKmlSimpleData->set_name ( name );
     638                 :                 poKmlSimpleData->set_text ( poOgrFeat->
     639               0 :                                             GetFieldAsString ( i ) );
     640                 : 
     641               0 :                 break;
     642                 :             }
     643                 : 
     644                 :         case OFTInteger:       //    Simple 32bit integer
     645                 : 
     646                 :             /***** extrude *****/
     647                 : 
     648               0 :             if ( EQUAL ( name, extrudefield ) ) {
     649                 : 
     650               0 :                 if ( poKmlPlacemark->has_geometry (  )
     651                 :                      && -1 < poOgrFeat->GetFieldAsInteger ( i ) ) {
     652                 :                     GeometryPtr poKmlGeometry =
     653               0 :                         poKmlPlacemark->get_geometry (  );
     654                 :                     ogr2extrude_rec ( poOgrFeat->GetFieldAsInteger ( i ),
     655               0 :                                       poKmlGeometry );
     656                 :                 }
     657               0 :                 continue;
     658                 :             }
     659                 : 
     660                 :             /***** tessellate *****/
     661                 : 
     662                 : 
     663               0 :             if ( EQUAL ( name, tessellatefield ) ) {
     664                 : 
     665               0 :                 if ( poKmlPlacemark->has_geometry (  )
     666                 :                      && -1 < poOgrFeat->GetFieldAsInteger ( i ) ) {
     667                 :                     GeometryPtr poKmlGeometry =
     668               0 :                         poKmlPlacemark->get_geometry (  );
     669                 :                     ogr2tessellate_rec ( poOgrFeat->GetFieldAsInteger ( i ),
     670               0 :                                          poKmlGeometry );
     671                 :                 }
     672                 : 
     673               0 :                 continue;
     674                 :             }
     675                 : 
     676                 : 
     677                 :             /***** visibility *****/
     678                 : 
     679               0 :             if ( EQUAL ( name, visibilityfield ) ) {
     680               0 :                 if ( -1 < poOgrFeat->GetFieldAsInteger ( i ) )
     681                 :                     poKmlPlacemark->set_visibility ( poOgrFeat->
     682               0 :                                                      GetFieldAsInteger ( i ) );
     683                 : 
     684               0 :                 continue;
     685                 :             }
     686                 : 
     687                 :             /***** other *****/
     688                 : 
     689               0 :             poKmlSimpleData = poKmlFactory->CreateSimpleData (  );
     690               0 :             poKmlSimpleData->set_name ( name );
     691               0 :             poKmlSimpleData->set_text ( poOgrFeat->GetFieldAsString ( i ) );
     692                 : 
     693               0 :             break;
     694                 : 
     695                 :         case OFTReal:          //   Double Precision floating point
     696                 :         {
     697               0 :             poKmlSimpleData = poKmlFactory->CreateSimpleData (  );
     698               0 :             poKmlSimpleData->set_name ( name );
     699                 : 
     700               0 :             char* pszStr = CPLStrdup( poOgrFeat->GetFieldAsString ( i ) );
     701                 :             /* Use point as decimal separator */
     702               0 :             char* pszComma = strchr(pszStr, ',');
     703               0 :             if (pszComma)
     704               0 :                 *pszComma = '.';
     705               0 :             poKmlSimpleData->set_text ( pszStr );
     706               0 :             CPLFree(pszStr);
     707                 : 
     708               0 :             break;
     709                 :         }
     710                 : 
     711                 :         case OFTStringList:    //     Array of strings
     712                 :         case OFTIntegerList:   //    List of 32bit integers
     713                 :         case OFTRealList:   //    List of doubles
     714                 :         case OFTBinary:        //     Raw Binary data
     715                 :         case OFTWideStringList:    //     deprecated
     716                 :         default:
     717                 : 
     718                 :         /***** other *****/
     719                 : 
     720               0 :             poKmlSimpleData = poKmlFactory->CreateSimpleData (  );
     721               0 :             poKmlSimpleData->set_name ( name );
     722               0 :             poKmlSimpleData->set_text ( poOgrFeat->GetFieldAsString ( i ) );
     723                 : 
     724                 :             break;
     725                 :         }
     726               3 :         poKmlSchemaData->add_simpledata ( poKmlSimpleData );
     727                 :     }
     728                 : 
     729                 :     /***** dont add it to the placemark unless there is data *****/
     730                 : 
     731              27 :     if ( poKmlSchemaData->get_simpledata_array_size (  ) > 0 ) {
     732                 :         ExtendedDataPtr poKmlExtendedData =
     733               3 :             poKmlFactory->CreateExtendedData (  );
     734               3 :         poKmlExtendedData->add_schemadata ( poKmlSchemaData );
     735               3 :         poKmlPlacemark->set_extendeddata ( poKmlExtendedData );
     736                 :     }
     737                 : 
     738              27 :     return;
     739                 : }
     740                 : 
     741                 : /******************************************************************************
     742                 :  recursive function to read altitude mode from the geometry
     743                 : ******************************************************************************/
     744                 : 
     745             374 : int kml2altitudemode_rec (
     746                 :     GeometryPtr poKmlGeometry,
     747                 :     int *pnAltitudeMode,
     748                 :     int *pbIsGX )
     749                 : {
     750                 : 
     751             374 :     PointPtr poKmlPoint;
     752             374 :     LineStringPtr poKmlLineString;
     753             374 :     PolygonPtr poKmlPolygon;
     754             374 :     MultiGeometryPtr poKmlMultiGeometry;
     755                 : 
     756                 :     size_t nGeom;
     757                 :     size_t i;
     758                 : 
     759             374 :     switch ( poKmlGeometry->Type (  ) ) {
     760                 : 
     761                 :     case kmldom::Type_Point:
     762              91 :         poKmlPoint = AsPoint ( poKmlGeometry );
     763                 : 
     764              91 :         if ( poKmlPoint->has_altitudemode (  ) ) {
     765              30 :             *pnAltitudeMode = poKmlPoint->get_altitudemode (  );
     766              30 :             return TRUE;
     767                 :         }
     768              61 :         else if ( poKmlPoint->has_gx_altitudemode (  ) ) {
     769               0 :             *pnAltitudeMode = poKmlPoint->get_gx_altitudemode (  );
     770               0 :             *pbIsGX = TRUE;
     771               0 :             return TRUE;
     772                 :         }
     773                 : 
     774              61 :         break;
     775                 : 
     776                 :     case kmldom::Type_LineString:
     777             105 :         poKmlLineString = AsLineString ( poKmlGeometry );
     778                 : 
     779             105 :         if ( poKmlLineString->has_altitudemode (  ) ) {
     780              54 :             *pnAltitudeMode = poKmlLineString->get_altitudemode (  );
     781              54 :             return TRUE;
     782                 :         }
     783              51 :         else if ( poKmlLineString->has_gx_altitudemode (  ) ) {
     784               0 :             *pnAltitudeMode = poKmlLineString->get_gx_altitudemode (  );
     785               0 :             *pbIsGX = TRUE;
     786               0 :             return TRUE;
     787                 :         }
     788              51 :         break;
     789                 : 
     790                 :     case kmldom::Type_LinearRing:
     791               3 :         break;
     792                 : 
     793                 :     case kmldom::Type_Polygon:
     794             156 :         poKmlPolygon = AsPolygon ( poKmlGeometry );
     795                 : 
     796             156 :         if ( poKmlPolygon->has_altitudemode (  ) ) {
     797             137 :             *pnAltitudeMode = poKmlPolygon->get_altitudemode (  );
     798             137 :             return TRUE;
     799                 :         }
     800              19 :         else if ( poKmlPolygon->has_gx_altitudemode (  ) ) {
     801               0 :             *pnAltitudeMode = poKmlPolygon->get_gx_altitudemode (  );
     802               0 :             *pbIsGX = TRUE;
     803               0 :             return TRUE;
     804                 :         }
     805                 : 
     806              19 :         break;
     807                 : 
     808                 :     case kmldom::Type_MultiGeometry:
     809              19 :         poKmlMultiGeometry = AsMultiGeometry ( poKmlGeometry );
     810                 : 
     811              19 :         nGeom = poKmlMultiGeometry->get_geometry_array_size (  );
     812              50 :         for ( i = 0; i < nGeom; i++ ) {
     813              31 :             if ( kml2altitudemode_rec ( poKmlMultiGeometry->
     814                 :                                         get_geometry_array_at ( i ),
     815                 :                                         pnAltitudeMode, pbIsGX ) )
     816               0 :                 return TRUE;
     817                 :         }
     818                 : 
     819                 :         break;
     820                 : 
     821                 :     default:
     822                 :         break;
     823                 : 
     824                 :     }
     825                 : 
     826             153 :     return FALSE;
     827                 : }
     828                 : 
     829                 : /******************************************************************************
     830                 :  recursive function to read extrude from the geometry
     831                 : ******************************************************************************/
     832                 : 
     833             374 : int kml2extrude_rec (
     834                 :     GeometryPtr poKmlGeometry,
     835                 :     int *pnExtrude )
     836                 : {
     837                 : 
     838             374 :     PointPtr poKmlPoint;
     839             374 :     LineStringPtr poKmlLineString;
     840             374 :     PolygonPtr poKmlPolygon;
     841             374 :     MultiGeometryPtr poKmlMultiGeometry;
     842                 : 
     843                 :     size_t nGeom;
     844                 :     size_t i;
     845                 : 
     846             374 :     switch ( poKmlGeometry->Type (  ) ) {
     847                 : 
     848                 :     case kmldom::Type_Point:
     849              91 :         poKmlPoint = AsPoint ( poKmlGeometry );
     850                 : 
     851              91 :         if ( poKmlPoint->has_extrude (  ) ) {
     852              15 :             *pnExtrude = poKmlPoint->get_extrude (  );
     853              15 :             return TRUE;
     854                 :         }
     855                 : 
     856              76 :         break;
     857                 : 
     858                 :     case kmldom::Type_LineString:
     859             105 :         poKmlLineString = AsLineString ( poKmlGeometry );
     860                 : 
     861             105 :         if ( poKmlLineString->has_extrude (  ) ) {
     862              26 :             *pnExtrude = poKmlLineString->get_extrude (  );
     863              26 :             return TRUE;
     864                 :         }
     865                 : 
     866              79 :         break;
     867                 : 
     868                 :     case kmldom::Type_LinearRing:
     869               3 :         break;
     870                 : 
     871                 :     case kmldom::Type_Polygon:
     872             156 :         poKmlPolygon = AsPolygon ( poKmlGeometry );
     873                 : 
     874             156 :         if ( poKmlPolygon->has_extrude (  ) ) {
     875             107 :             *pnExtrude = poKmlPolygon->get_extrude (  );
     876             107 :             return TRUE;
     877                 :         }
     878                 : 
     879              49 :         break;
     880                 : 
     881                 :     case kmldom::Type_MultiGeometry:
     882              19 :         poKmlMultiGeometry = AsMultiGeometry ( poKmlGeometry );
     883                 : 
     884              19 :         nGeom = poKmlMultiGeometry->get_geometry_array_size (  );
     885              50 :         for ( i = 0; i < nGeom; i++ ) {
     886              31 :             if ( kml2extrude_rec ( poKmlMultiGeometry->
     887                 :                                    get_geometry_array_at ( i ), pnExtrude ) )
     888               0 :                 return TRUE;
     889                 :         }
     890                 : 
     891                 :         break;
     892                 : 
     893                 :     default:
     894                 :         break;
     895                 : 
     896                 :     }
     897                 : 
     898             226 :     return FALSE;
     899                 : }
     900                 : 
     901                 : /******************************************************************************
     902                 :  recursive function to read tessellate from the geometry
     903                 : ******************************************************************************/
     904                 : 
     905             374 : int kml2tessellate_rec (
     906                 :     GeometryPtr poKmlGeometry,
     907                 :     int *pnTessellate )
     908                 : {
     909                 : 
     910             374 :     LineStringPtr poKmlLineString;
     911             374 :     PolygonPtr poKmlPolygon;
     912             374 :     MultiGeometryPtr poKmlMultiGeometry;
     913                 : 
     914                 :     size_t nGeom;
     915                 :     size_t i;
     916                 : 
     917             374 :     switch ( poKmlGeometry->Type (  ) ) {
     918                 : 
     919                 :     case kmldom::Type_Point:
     920              91 :         break;
     921                 : 
     922                 :     case kmldom::Type_LineString:
     923             105 :         poKmlLineString = AsLineString ( poKmlGeometry );
     924                 : 
     925             105 :         if ( poKmlLineString->has_tessellate (  ) ) {
     926              88 :             *pnTessellate = poKmlLineString->get_tessellate (  );
     927              88 :             return TRUE;
     928                 :         }
     929                 : 
     930              17 :         break;
     931                 : 
     932                 :     case kmldom::Type_LinearRing:
     933               3 :         break;
     934                 : 
     935                 :     case kmldom::Type_Polygon:
     936             156 :         poKmlPolygon = AsPolygon ( poKmlGeometry );
     937                 : 
     938             156 :         if ( poKmlPolygon->has_tessellate (  ) ) {
     939              56 :             *pnTessellate = poKmlPolygon->get_tessellate (  );
     940              56 :             return TRUE;
     941                 :         }
     942                 : 
     943             100 :         break;
     944                 : 
     945                 :     case kmldom::Type_MultiGeometry:
     946              19 :         poKmlMultiGeometry = AsMultiGeometry ( poKmlGeometry );
     947                 : 
     948              19 :         nGeom = poKmlMultiGeometry->get_geometry_array_size (  );
     949              50 :         for ( i = 0; i < nGeom; i++ ) {
     950              31 :             if ( kml2tessellate_rec ( poKmlMultiGeometry->
     951                 :                                       get_geometry_array_at ( i ),
     952                 :                                       pnTessellate ) )
     953               0 :                 return TRUE;
     954                 :         }
     955                 : 
     956                 :         break;
     957                 : 
     958                 :     default:
     959                 :         break;
     960                 : 
     961                 :     }
     962                 : 
     963             230 :     return FALSE;
     964                 : }
     965                 : 
     966                 : /******************************************************************************
     967                 :  function to read kml into ogr fields
     968                 : ******************************************************************************/
     969                 : 
     970             376 : void kml2field (
     971                 :     OGRFeature * poOgrFeat,
     972                 :     FeaturePtr poKmlFeature )
     973                 : {
     974                 : 
     975             376 :     const char *namefield = CPLGetConfigOption ( "LIBKML_NAME_FIELD", "Name" );
     976                 :     const char *descfield =
     977             376 :         CPLGetConfigOption ( "LIBKML_DESCRIPTION_FIELD", "description" );
     978                 :     const char *tsfield =
     979             376 :         CPLGetConfigOption ( "LIBKML_TIMESTAMP_FIELD", "timestamp" );
     980                 :     const char *beginfield =
     981             376 :         CPLGetConfigOption ( "LIBKML_BEGIN_FIELD", "begin" );
     982             376 :     const char *endfield = CPLGetConfigOption ( "LIBKML_END_FIELD", "end" );
     983                 :     const char *altitudeModefield =
     984             376 :         CPLGetConfigOption ( "LIBKML_ALTITUDEMODE_FIELD", "altitudeMode" );
     985                 :     const char *tessellatefield =
     986             376 :         CPLGetConfigOption ( "LIBKML_TESSELLATE_FIELD", "tessellate" );
     987                 :     const char *extrudefield =
     988             376 :         CPLGetConfigOption ( "LIBKML_EXTRUDE_FIELD", "extrude" );
     989                 :     const char *visibilityfield =
     990             376 :         CPLGetConfigOption ( "LIBKML_VISIBILITY_FIELD", "visibility" );
     991                 :     const char *drawOrderfield =
     992             376 :         CPLGetConfigOption ( "LIBKML_DRAWORDER_FIELD", "drawOrder" );
     993                 :     const char *iconfield =
     994             376 :         CPLGetConfigOption ( "LIBKML_ICON_FIELD", "icon" );
     995                 : 
     996                 :     /***** name *****/
     997                 : 
     998             376 :     if ( poKmlFeature->has_name (  ) ) {
     999             328 :         const std::string oKmlName = poKmlFeature->get_name (  );
    1000             328 :         int iField = poOgrFeat->GetFieldIndex ( namefield );
    1001                 : 
    1002             328 :         if ( iField > -1 )
    1003             328 :             poOgrFeat->SetField ( iField, oKmlName.c_str (  ) );
    1004                 :     }
    1005                 : 
    1006                 :     /***** description *****/
    1007                 : 
    1008             376 :     if ( poKmlFeature->has_description (  ) ) {
    1009             173 :         const std::string oKmlDesc = poKmlFeature->get_description (  );
    1010             173 :         int iField = poOgrFeat->GetFieldIndex ( descfield );
    1011                 : 
    1012             173 :         if ( iField > -1 )
    1013             173 :             poOgrFeat->SetField ( iField, oKmlDesc.c_str (  ) );
    1014                 :     }
    1015                 : 
    1016             376 :     if ( poKmlFeature->has_timeprimitive (  ) ) {
    1017                 :         TimePrimitivePtr poKmlTimePrimitive =
    1018               0 :             poKmlFeature->get_timeprimitive (  );
    1019                 : 
    1020                 :         /***** timestamp *****/
    1021                 : 
    1022               0 :         if ( poKmlTimePrimitive->IsA ( kmldom::Type_TimeStamp ) ) {
    1023               0 :             TimeStampPtr poKmlTimeStamp = AsTimeStamp ( poKmlTimePrimitive );
    1024                 : 
    1025               0 :             if ( poKmlTimeStamp->has_when (  ) ) {
    1026               0 :                 const std::string oKmlWhen = poKmlTimeStamp->get_when (  );
    1027                 : 
    1028                 : 
    1029               0 :                 int iField = poOgrFeat->GetFieldIndex ( tsfield );
    1030                 : 
    1031               0 :                 if ( iField > -1 ) {
    1032                 :                     int nYear,
    1033                 :                         nMonth,
    1034                 :                         nDay,
    1035                 :                         nHour,
    1036                 :                         nMinute,
    1037                 :                         nTZ;
    1038                 :                     float fSecond;
    1039                 : 
    1040               0 :                     if ( OGRParseXMLDateTime
    1041                 :                          ( oKmlWhen.c_str (  ), &nYear, &nMonth, &nDay, &nHour,
    1042                 :                            &nMinute, &fSecond, &nTZ ) )
    1043                 :                         poOgrFeat->SetField ( iField, nYear, nMonth, nDay,
    1044                 :                                               nHour, nMinute, ( int )fSecond,
    1045               0 :                                               nTZ );
    1046               0 :                 }
    1047               0 :             }
    1048                 :         }
    1049                 : 
    1050                 :         /***** timespan *****/
    1051                 : 
    1052               0 :         if ( poKmlTimePrimitive->IsA ( kmldom::Type_TimeSpan ) ) {
    1053               0 :             TimeSpanPtr poKmlTimeSpan = AsTimeSpan ( poKmlTimePrimitive );
    1054                 : 
    1055                 :             /***** begin *****/
    1056                 : 
    1057               0 :             if ( poKmlTimeSpan->has_begin (  ) ) {
    1058               0 :                 const std::string oKmlWhen = poKmlTimeSpan->get_begin (  );
    1059                 : 
    1060                 : 
    1061               0 :                 int iField = poOgrFeat->GetFieldIndex ( beginfield );
    1062                 : 
    1063               0 :                 if ( iField > -1 ) {
    1064                 :                     int nYear,
    1065                 :                         nMonth,
    1066                 :                         nDay,
    1067                 :                         nHour,
    1068                 :                         nMinute,
    1069                 :                         nTZ;
    1070                 :                     float fSecond;
    1071                 : 
    1072               0 :                     if ( OGRParseXMLDateTime
    1073                 :                          ( oKmlWhen.c_str (  ), &nYear, &nMonth, &nDay, &nHour,
    1074                 :                            &nMinute, &fSecond, &nTZ ) )
    1075                 :                         poOgrFeat->SetField ( iField, nYear, nMonth, nDay,
    1076                 :                                               nHour, nMinute, ( int )fSecond,
    1077               0 :                                               nTZ );
    1078               0 :                 }
    1079                 :             }
    1080                 : 
    1081                 :             /***** end *****/
    1082                 : 
    1083               0 :             if ( poKmlTimeSpan->has_end (  ) ) {
    1084               0 :                 const std::string oKmlWhen = poKmlTimeSpan->get_end (  );
    1085                 : 
    1086                 : 
    1087               0 :                 int iField = poOgrFeat->GetFieldIndex ( endfield );
    1088                 : 
    1089               0 :                 if ( iField > -1 ) {
    1090                 :                     int nYear,
    1091                 :                         nMonth,
    1092                 :                         nDay,
    1093                 :                         nHour,
    1094                 :                         nMinute,
    1095                 :                         nTZ;
    1096                 :                     float fSecond;
    1097                 : 
    1098               0 :                     if ( OGRParseXMLDateTime
    1099                 :                          ( oKmlWhen.c_str (  ), &nYear, &nMonth, &nDay, &nHour,
    1100                 :                            &nMinute, &fSecond, &nTZ ) )
    1101                 :                         poOgrFeat->SetField ( iField, nYear, nMonth, nDay,
    1102                 :                                               nHour, nMinute, ( int )fSecond,
    1103               0 :                                               nTZ );
    1104               0 :                 }
    1105               0 :             }
    1106               0 :         }
    1107                 :     }
    1108                 : 
    1109                 : 
    1110                 :     /***** placemark *****/
    1111             376 :     PlacemarkPtr poKmlPlacemark = AsPlacemark ( poKmlFeature );
    1112             376 :     GroundOverlayPtr poKmlGroundOverlay = AsGroundOverlay ( poKmlFeature );
    1113             376 :     if ( poKmlPlacemark && poKmlPlacemark->has_geometry (  ) ) {
    1114             343 :         GeometryPtr poKmlGeometry = poKmlPlacemark->get_geometry (  );
    1115                 : 
    1116                 :         /***** altitudeMode *****/
    1117                 : 
    1118                 : 
    1119             343 :         int bIsGX = FALSE;
    1120             343 :         int nAltitudeMode = -1;
    1121                 : 
    1122             343 :         int iField = poOgrFeat->GetFieldIndex ( altitudeModefield );
    1123                 : 
    1124             343 :         if ( iField > -1 ) {
    1125                 : 
    1126             343 :             if ( kml2altitudemode_rec ( poKmlGeometry,
    1127                 :                                         &nAltitudeMode, &bIsGX ) ) {
    1128                 : 
    1129             221 :                 if ( !bIsGX ) {
    1130                 : 
    1131             221 :                     switch ( nAltitudeMode ) {
    1132                 :                     case kmldom::ALTITUDEMODE_CLAMPTOGROUND:
    1133               0 :                         poOgrFeat->SetField ( iField, "clampToGround" );
    1134               0 :                         break;
    1135                 : 
    1136                 :                     case kmldom::ALTITUDEMODE_RELATIVETOGROUND:
    1137             163 :                         poOgrFeat->SetField ( iField, "relativeToGround" );
    1138             163 :                         break;
    1139                 : 
    1140                 :                     case kmldom::ALTITUDEMODE_ABSOLUTE:
    1141              58 :                         poOgrFeat->SetField ( iField, "absolute" );
    1142                 :                         break;
    1143                 : 
    1144                 :                     }
    1145                 :                 }
    1146                 : 
    1147                 :                 else {
    1148               0 :                     switch ( nAltitudeMode ) {
    1149                 :                     case kmldom::GX_ALTITUDEMODE_RELATIVETOSEAFLOOR:
    1150               0 :                         poOgrFeat->SetField ( iField, "relativeToSeaFloor" );
    1151               0 :                         break;
    1152                 : 
    1153                 :                     case kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR:
    1154               0 :                         poOgrFeat->SetField ( iField, "clampToSeaFloor" );
    1155                 :                         break;
    1156                 :                     }
    1157                 : 
    1158                 :                 }
    1159                 :             }
    1160                 : 
    1161                 :         }
    1162                 : 
    1163                 :         /***** tessellate *****/
    1164                 : 
    1165             343 :         int nTessellate = -1;
    1166                 : 
    1167             343 :         kml2tessellate_rec ( poKmlGeometry, &nTessellate );
    1168                 : 
    1169             343 :         iField = poOgrFeat->GetFieldIndex ( tessellatefield );
    1170             343 :         if ( iField > -1 )
    1171             343 :             poOgrFeat->SetField ( iField, nTessellate );
    1172                 : 
    1173                 :         /***** extrude *****/
    1174                 : 
    1175             343 :         int nExtrude = -1;
    1176                 : 
    1177             343 :         kml2extrude_rec ( poKmlGeometry, &nExtrude );
    1178                 : 
    1179             343 :         iField = poOgrFeat->GetFieldIndex ( extrudefield );
    1180             343 :         if ( iField > -1 )
    1181             343 :             poOgrFeat->SetField ( iField, nExtrude );
    1182                 : 
    1183                 :     }
    1184                 : 
    1185                 :     /***** ground overlay *****/
    1186                 : 
    1187              33 :     else if ( poKmlGroundOverlay ) {
    1188                 : 
    1189                 :         /***** icon *****/
    1190                 : 
    1191              18 :         int iField = poOgrFeat->GetFieldIndex ( iconfield );
    1192              18 :         if ( iField > -1 ) {
    1193                 : 
    1194              18 :             if ( poKmlGroundOverlay->has_icon (  ) ) {
    1195              18 :                 IconPtr icon = poKmlGroundOverlay->get_icon (  );
    1196              18 :                 if ( icon->has_href (  ) ) {
    1197              18 :                     poOgrFeat->SetField ( iField, icon->get_href (  ).c_str (  ) );
    1198              18 :                 }
    1199                 :             }
    1200                 :         }
    1201                 : 
    1202                 :         /***** drawOrder *****/
    1203                 : 
    1204                 : 
    1205              18 :         iField = poOgrFeat->GetFieldIndex ( drawOrderfield );
    1206              18 :         if ( iField > -1 ) {
    1207                 : 
    1208              18 :             if ( poKmlGroundOverlay->has_draworder (  ) ) {
    1209               0 :                 poOgrFeat->SetField ( iField, poKmlGroundOverlay->get_draworder (  ) );
    1210                 :             }
    1211                 :         }
    1212                 : 
    1213                 :         /***** altitudeMode *****/
    1214                 : 
    1215              18 :         iField = poOgrFeat->GetFieldIndex ( altitudeModefield );
    1216                 : 
    1217              18 :         if ( iField > -1 ) {
    1218                 : 
    1219              18 :             if ( poKmlGroundOverlay->has_altitudemode (  ) ) {
    1220               0 :                 switch ( poKmlGroundOverlay->get_altitudemode (  ) ) {
    1221                 :                 case kmldom::ALTITUDEMODE_CLAMPTOGROUND:
    1222               0 :                     poOgrFeat->SetField ( iField, "clampToGround" );
    1223               0 :                     break;
    1224                 : 
    1225                 :                 case kmldom::ALTITUDEMODE_RELATIVETOGROUND:
    1226               0 :                     poOgrFeat->SetField ( iField, "relativeToGround" );
    1227               0 :                     break;
    1228                 : 
    1229                 :                 case kmldom::ALTITUDEMODE_ABSOLUTE:
    1230               0 :                     poOgrFeat->SetField ( iField, "absolute" );
    1231                 :                     break;
    1232                 : 
    1233                 :                 }
    1234              18 :             } else if ( poKmlGroundOverlay->has_gx_altitudemode (  ) ) {
    1235               0 :                 switch ( poKmlGroundOverlay->get_gx_altitudemode ( ) ) {
    1236                 :                 case kmldom::GX_ALTITUDEMODE_RELATIVETOSEAFLOOR:
    1237               0 :                     poOgrFeat->SetField ( iField, "relativeToSeaFloor" );
    1238               0 :                     break;
    1239                 : 
    1240                 :                 case kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR:
    1241               0 :                     poOgrFeat->SetField ( iField, "clampToSeaFloor" );
    1242                 :                     break;
    1243                 :                 }
    1244                 :             }
    1245                 : 
    1246                 :         }
    1247                 :     }
    1248                 : 
    1249                 :     /***** visibility *****/
    1250                 : 
    1251             376 :     int nVisibility = -1;
    1252                 : 
    1253             376 :     if ( poKmlFeature->has_visibility (  ) )
    1254             287 :         nVisibility = poKmlFeature->get_visibility (  );
    1255                 : 
    1256             376 :     int iField = poOgrFeat->GetFieldIndex ( visibilityfield );
    1257                 : 
    1258             376 :     if ( iField > -1 )
    1259             376 :         poOgrFeat->SetField ( iField, nVisibility );
    1260                 : 
    1261             376 :     ExtendedDataPtr poKmlExtendedData = NULL;
    1262                 : 
    1263             376 :     if ( poKmlFeature->has_extendeddata (  ) ) {
    1264               5 :         poKmlExtendedData = poKmlFeature->get_extendeddata (  );
    1265                 : 
    1266                 :         /***** loop over the schemadata_arrays *****/
    1267                 : 
    1268               5 :         size_t nSchemaData = poKmlExtendedData->get_schemadata_array_size (  );
    1269                 : 
    1270                 :         size_t iSchemaData;
    1271                 : 
    1272              10 :         for ( iSchemaData = 0; iSchemaData < nSchemaData; iSchemaData++ ) {
    1273                 :             SchemaDataPtr poKmlSchemaData =
    1274               5 :                 poKmlExtendedData->get_schemadata_array_at ( iSchemaData );
    1275                 : 
    1276                 :             /***** loop over the simpledata array *****/
    1277                 : 
    1278                 :             size_t nSimpleData =
    1279               5 :                 poKmlSchemaData->get_simpledata_array_size (  );
    1280                 : 
    1281                 :             size_t iSimpleData;
    1282                 : 
    1283              10 :             for ( iSimpleData = 0; iSimpleData < nSimpleData; iSimpleData++ ) {
    1284                 :                 SimpleDataPtr poKmlSimpleData =
    1285               5 :                     poKmlSchemaData->get_simpledata_array_at ( iSimpleData );
    1286                 : 
    1287                 :                 /***** find the field index *****/
    1288                 : 
    1289               5 :                 int iField = -1;
    1290                 : 
    1291               5 :                 if ( poKmlSimpleData->has_name (  ) ) {
    1292               5 :                     const string oName = poKmlSimpleData->get_name (  );
    1293               5 :                     const char *pszName = oName.c_str (  );
    1294                 : 
    1295               5 :                     iField = poOgrFeat->GetFieldIndex ( pszName );
    1296                 :                 }
    1297                 : 
    1298                 :                 /***** if it has trxt set the field *****/
    1299                 : 
    1300               5 :                 if ( iField > -1 && poKmlSimpleData->has_text (  ) ) {
    1301               5 :                     string oText = poKmlSimpleData->get_text (  );
    1302                 : 
    1303                 :                     /* SerializePretty() adds a new line before the data */
    1304                 :                     /* ands trailing spaces. I believe this is wrong */
    1305                 :                     /* as it breaks round-tripping */
    1306                 : 
    1307                 :                     /* Trim trailing spaces */
    1308              42 :                     while (oText.size() != 0 && oText[oText.size()-1] == ' ')
    1309              32 :                         oText.resize(oText.size()-1);
    1310                 : 
    1311                 :                     /* Skip leading newline and spaces */
    1312               5 :                     const char* pszText = oText.c_str (  );
    1313               5 :                     if (pszText[0] == '\n')
    1314               3 :                         pszText ++;
    1315              10 :                     while (pszText[0] == ' ')
    1316               0 :                         pszText ++;
    1317                 : 
    1318               5 :                     poOgrFeat->SetField ( iField, pszText );
    1319                 :                 }
    1320                 :             }
    1321                 :         }
    1322                 : 
    1323               5 :         if (nSchemaData == 0 &&  poKmlExtendedData->get_data_array_size() > 0 )
    1324                 :         {
    1325                 :             int bLaunderFieldNames =
    1326               0 :                         CSLTestBoolean(CPLGetConfigOption("LIBKML_LAUNDER_FIELD_NAMES", "YES"));
    1327               0 :             size_t nDataArraySize = poKmlExtendedData->get_data_array_size();
    1328               0 :             for(size_t i=0; i < nDataArraySize; i++)
    1329                 :             {
    1330               0 :                 const DataPtr& data = poKmlExtendedData->get_data_array_at(i);
    1331               0 :                 if (data->has_name() && data->has_value())
    1332                 :                 {
    1333               0 :                     CPLString osName = data->get_name();
    1334               0 :                     if (bLaunderFieldNames)
    1335               0 :                         osName = OGRLIBKMLLayer::LaunderFieldNames(osName);
    1336               0 :                     int iField = poOgrFeat->GetFieldIndex ( osName );
    1337               0 :                     if (iField >= 0)
    1338                 :                     {
    1339               0 :                         poOgrFeat->SetField ( iField, data->get_value().c_str() );
    1340               0 :                     }
    1341                 :                 }
    1342                 :             }
    1343                 :         }
    1344             376 :     }
    1345                 : 
    1346             376 : }
    1347                 : 
    1348                 : /******************************************************************************
    1349                 :  function create a simplefield from a FieldDefn
    1350                 : ******************************************************************************/
    1351                 : 
    1352               9 : SimpleFieldPtr FieldDef2kml (
    1353                 :     OGRFieldDefn * poOgrFieldDef,
    1354                 :     KmlFactory * poKmlFactory )
    1355                 : {
    1356                 : 
    1357               9 :     SimpleFieldPtr poKmlSimpleField = poKmlFactory->CreateSimpleField (  );
    1358               9 :     const char *pszFieldName = poOgrFieldDef->GetNameRef (  );
    1359                 : 
    1360               9 :     poKmlSimpleField->set_name ( pszFieldName );
    1361                 : 
    1362              18 :     const char *namefield = CPLGetConfigOption ( "LIBKML_NAME_FIELD", "Name" );
    1363                 :     const char *descfield =
    1364               9 :         CPLGetConfigOption ( "LIBKML_DESCRIPTION_FIELD", "description" );
    1365                 :     const char *tsfield =
    1366               9 :         CPLGetConfigOption ( "LIBKML_TIMESTAMP_FIELD", "timestamp" );
    1367                 :     const char *beginfield =
    1368               9 :         CPLGetConfigOption ( "LIBKML_BEGIN_FIELD", "begin" );
    1369               9 :     const char *endfield = CPLGetConfigOption ( "LIBKML_END_FIELD", "end" );
    1370                 :     const char *altitudeModefield =
    1371               9 :         CPLGetConfigOption ( "LIBKML_ALTITUDEMODE_FIELD", "altitudeMode" );
    1372                 :     const char *tessellatefield =
    1373               9 :         CPLGetConfigOption ( "LIBKML_TESSELLATE_FIELD", "tessellate" );
    1374                 :     const char *extrudefield =
    1375               9 :         CPLGetConfigOption ( "LIBKML_EXTRUDE_FIELD", "extrude" );
    1376                 :     const char *visibilityfield =
    1377               9 :         CPLGetConfigOption ( "LIBKML_VISIBILITY_FIELD", "visibility" );
    1378                 : 
    1379                 : 
    1380               9 :     SimpleDataPtr poKmlSimpleData = NULL;
    1381                 : 
    1382               9 :     switch ( poOgrFieldDef->GetType (  ) ) {
    1383                 : 
    1384                 :     case OFTInteger:
    1385                 :     case OFTIntegerList:
    1386               0 :         if ( EQUAL ( pszFieldName, tessellatefield ) ||
    1387                 :              EQUAL ( pszFieldName, extrudefield ) ||
    1388                 :              EQUAL ( pszFieldName, visibilityfield ) )
    1389               0 :             break;
    1390               0 :         poKmlSimpleField->set_type ( "int" );
    1391               0 :         return poKmlSimpleField;
    1392                 :     case OFTReal:
    1393                 :     case OFTRealList:
    1394               0 :         poKmlSimpleField->set_type ( "float" );
    1395               0 :         return poKmlSimpleField;
    1396                 :     case OFTBinary:
    1397               0 :         poKmlSimpleField->set_type ( "bool" );
    1398               0 :         return poKmlSimpleField;
    1399                 :     case OFTString:
    1400                 :     case OFTStringList:
    1401               9 :         if ( EQUAL ( pszFieldName, namefield ) ||
    1402                 :              EQUAL ( pszFieldName, descfield ) ||
    1403                 :              EQUAL ( pszFieldName, altitudeModefield ) )
    1404               6 :             break;
    1405               3 :         poKmlSimpleField->set_type ( "string" );
    1406               3 :         return poKmlSimpleField;
    1407                 : 
    1408                 :     /***** kml has these types but as timestamp/timespan *****/
    1409                 : 
    1410                 :     case OFTDate:
    1411                 :     case OFTTime:
    1412                 :     case OFTDateTime:
    1413               0 :         if ( EQUAL ( pszFieldName, tsfield )
    1414                 :              || EQUAL ( pszFieldName, beginfield )
    1415                 :              || EQUAL ( pszFieldName, endfield ) )
    1416               0 :             break;
    1417                 :     default:
    1418               0 :         poKmlSimpleField->set_type ( "string" );
    1419               0 :         return poKmlSimpleField;
    1420                 :     }
    1421                 : 
    1422               6 :     return NULL;
    1423                 : }
    1424                 : 
    1425                 : /******************************************************************************
    1426                 :  function to add the simpleFields in a schema to a featuredefn
    1427                 : ******************************************************************************/
    1428                 : 
    1429               5 : void kml2FeatureDef (
    1430                 :     SchemaPtr poKmlSchema,
    1431                 :     OGRFeatureDefn * poOgrFeatureDefn )
    1432                 : {
    1433                 : 
    1434               5 :     size_t nSimpleFields = poKmlSchema->get_simplefield_array_size (  );
    1435                 :     size_t iSimpleField;
    1436                 : 
    1437              10 :     for ( iSimpleField = 0; iSimpleField < nSimpleFields; iSimpleField++ ) {
    1438                 :         SimpleFieldPtr poKmlSimpleField =
    1439               5 :             poKmlSchema->get_simplefield_array_at ( iSimpleField );
    1440                 : 
    1441               5 :         const char *pszType = "string";
    1442               5 :   string osName = "Unknown";
    1443                 : 
    1444              10 :         if ( poKmlSimpleField->has_type (  ) ) {
    1445               5 :             const string oType = poKmlSimpleField->get_type (  );
    1446                 : 
    1447               5 :             pszType = oType.c_str (  );
    1448                 :         }
    1449                 : 
    1450                 :         /* FIXME? We cannot set displayname as the field name because in kml2field() we make the */
    1451                 :         /* lookup on fields based on their name. We would need some map if we really */
    1452                 :         /* want to use displayname, but that might not be a good idea because displayname */
    1453                 :         /* may have HTML formatting, which makes it impractical when converting to other */
    1454                 :         /* drivers or to make requests */
    1455                 :         /* Example: http://www.jasonbirch.com/files/newt_combined.kml */
    1456                 :         /*if ( poKmlSimpleField->has_displayname (  ) ) {
    1457                 :             osName = poKmlSimpleField->get_displayname (  );
    1458                 :         }
    1459                 : 
    1460               5 :         else*/ if ( poKmlSimpleField->has_name (  ) ) {
    1461               5 :             osName = poKmlSimpleField->get_name (  );
    1462                 :         }
    1463                 : 
    1464               5 :         if ( EQUAL ( pszType, "bool" ) ||
    1465                 :              EQUAL ( pszType, "int" ) ||
    1466                 :              EQUAL ( pszType, "short" ) ||
    1467                 :              EQUAL ( pszType, "ushort" ) ) {
    1468               0 :             OGRFieldDefn oOgrFieldName ( osName.c_str(), OFTInteger );
    1469               0 :             poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldName );
    1470                 :         }
    1471               5 :         else if ( EQUAL ( pszType, "float" ) ||
    1472                 :                   EQUAL ( pszType, "double" ) ||
    1473                 : 
    1474                 :                   /* a too big uint wouldn't fit in a int, so we map it to OFTReal for now ... */
    1475                 :                   EQUAL ( pszType, "uint" ) ) {
    1476               0 :             OGRFieldDefn oOgrFieldName ( osName.c_str(), OFTReal );
    1477               0 :             poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldName );
    1478                 :         }
    1479                 :         else /* string, or any other unrecognized type */
    1480                 :         {
    1481               5 :             OGRFieldDefn oOgrFieldName ( osName.c_str(), OFTString );
    1482               5 :             poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldName );
    1483                 :         }
    1484                 :     }
    1485                 : 
    1486                 :     return;
    1487            2139 : }

Generated by: LCOV version 1.7