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

Generated by: LCOV version 1.7