Changeset 12091

Show
Ignore:
Timestamp:
09/06/07 20:20:20 (1 year ago)
Author:
mloskot
Message:

Added new KML driver, developed by Jens Oberender within the Google Summer of Code 2007, to the repository (Ticket #1801).

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/gdal/ogr/ogrsf_frmts/kml/GNUmakefile

    r9790 r12091  
    33include ../../../GDALmake.opt 
    44 
    5 CORE_OBJ =      kmlfeatureclass.o kmlfeature.o ogr2kmlgeometry.o                
     5CORE_OBJ =      ogr2kmlgeometry.o 
    66 
    7 OGR_OBJ =       ogrkmldriver.o ogrkmldatasource.o ogrkmllayer.o 
     7OGR_OBJ =       ogrkmldriver.o ogrkmldatasource.o ogrkmllayer.o kml.o kmlvector.o kmlnode.o 
    88 
    99OBJ =   $(CORE_OBJ) $(OGR_OBJ) 
    1010 
    11 CPPFLAGS :=     -I.. -I../.. $(GDAL_INCLUDE)  $(CPPFLAGS) 
     11CPPFLAGS :=     -I.. -I../.. $(GDAL_INCLUDE)  $(CPPFLAGS) -Wall -ansi 
    1212#CFLAGS :=      $(filter-out -Wall,$(CFLAGS)) 
    1313 
     
    1818 
    1919 
     20 
  • trunk/gdal/ogr/ogrsf_frmts/kml/makefile.vc

    r9802 r12091  
    11 
    2 LL_OBJ  =       kmlfeatureclass.obj kmlfeature.obj ogr2kmlgeometry.obj 
     2LL_OBJ  =       kml.obj kmlvector.obj ogr2kmlgeometry.obj kmlnode.obj 
    33OGR_OBJ =       ogrkmldriver.obj ogrkmldatasource.obj ogrkmllayer.obj 
    44 
     
    99!INCLUDE $(GDAL_ROOT)\nmake.opt 
    1010 
    11 EXTRAFLAGS =    -I.. -I..\.. 
     11!IFDEF EXPAT_DIR 
     12EXTRAFLAGS =    -I.. -I..\.. $(EXPAT_INCLUDE) -DHAVE_EXPAT=1  
     13!ELSE 
     14EXTRAFLAGS =    -I.. -I..\.. -DHAVE_EXPAT=0 
     15!ENDIF 
     16 
    1217 
    1318default:        $(OBJ) 
  • trunk/gdal/ogr/ogrsf_frmts/kml/ogr2kmlgeometry.cpp

    r11885 r12091  
    236236                      "<Polygon>" ); 
    237237 
    238         OGRLinearRing *poExteriorRing = poPolygon->getExteriorRing();  
    239         if( poExteriorRing != NULL ) 
    240         { 
    241             /* Test if we need to reverse the winding order. The KML specification 
    242              * defines the front of a face as a LinearRing with anti-clockwise 
    243              * winding order. Full 3D implementations of KML, such as Google Earth, 
    244              * light the front of the face, not the rear. 
    245              * For the present case it's safe to assume that all faces exported 
    246              * from OGR should have anti-clockwise winding orders.  
    247              */ 
    248             if ( poExteriorRing->isClockwise() ) 
    249             {  
    250                 poExteriorRing->reverseWindingOrder();  
    251             }  
    252  
     238        if( poPolygon->getExteriorRing() != NULL ) 
     239        { 
    253240            AppendString( ppszText, pnLength, pnMaxLength, 
    254241                          "<outerBoundaryIs>" ); 
    255242 
    256             if( !OGR2KMLGeometryAppend( poExteriorRing, 
     243            if( !OGR2KMLGeometryAppend( poPolygon->getExteriorRing(),  
    257244                                        ppszText, pnLength, pnMaxLength ) ) 
    258             { 
    259245                return FALSE; 
    260             } 
    261  
     246             
    262247            AppendString( ppszText, pnLength, pnMaxLength, 
    263248                          "</outerBoundaryIs>" ); 
     
    267252        { 
    268253            OGRLinearRing *poRing = poPolygon->getInteriorRing(iRing); 
    269  
    270             /* Perform the winding test again. */ 
    271             if( poRing->isClockwise() )  
    272             {  
    273                 poRing->reverseWindingOrder();  
    274             }  
    275254 
    276255            AppendString( ppszText, pnLength, pnMaxLength, 
  • trunk/gdal/ogr/ogrsf_frmts/kml/ogr_kml.h

    r10645 r12091  
    55 * Purpose:  Declarations for OGR wrapper classes for KML, and OGR->KML 
    66 *           translation of geometry. 
    7  * Author:   Christopher Condit, condit@sdsc.edu 
     7 * Author:   Christopher Condit, condit@sdsc.edu; 
     8 *           Jens Oberender, j.obi@troja.net 
    89 * 
    910 ****************************************************************************** 
    1011 * Copyright (c) 2006, Christopher Condit 
     12 *               2007, Jens Oberender 
    1113 * 
    1214 * Permission is hereby granted, free of charge, to any person obtaining a 
     
    3234 
    3335#include "ogrsf_frmts.h" 
    34 #include "kmlreader.h" 
     36#include "kmlvector.h" 
    3537 
    3638class OGRKMLDataSource; 
     
    4244class OGRKMLLayer : public OGRLayer 
    4345{ 
     46private: 
    4447    OGRSpatialReference *poSRS; 
    4548    OGRFeatureDefn     *poFeatureDefn; 
    4649 
    47     int                 iNextKMLId; 
     50    unsigned short      iNextKMLId; 
     51    unsigned short      nNextFID; 
    4852    int                 nTotalKMLCount; 
    4953 
     
    5256    OGRKMLDataSource    *poDS; 
    5357 
    54     KMLFeatureClass     *poFClass
     58    unsigned short      nLayerNumber
    5559 
    5660  public: 
     
    7074 
    7175    OGRErr              CreateFeature( OGRFeature *poFeature ); 
    72      
     76 
    7377    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; } 
    7478 
     
    7781 
    7882    virtual OGRSpatialReference *GetSpatialRef(); 
     83     
     84    void                SetLayerNumber(unsigned short); 
    7985     
    8086    int                 TestCapability( const char * ); 
     
    8793class OGRKMLDataSource : public OGRDataSource 
    8894{ 
    89     OGRKMLLayer     **papoLayers; 
     95    OGRKMLLayer         **papoLayers; 
    9096    int                 nLayers; 
    9197     
    9298    char                *pszName; 
    9399     
    94     OGRKMLLayer         *TranslateKMLSchema( KMLFeatureClass * ); 
    95  
    96100    //The name of the field to use for  
    97101    char                *pszNameField; 
     
    106110    int                 nSchemaInsertLocation; 
    107111 
    108     // input related parameters. 
    109     //IKMLReader          *poReader; 
     112    KML                 *poKMLFile; 
    110113 
    111114    void                InsertHeader(); 
     
    132135 
    133136    FILE                *GetOutputFP() { return fpOutput; } 
    134     //IKMLReader          *GetReader() { return poReader; } 
    135137 
    136138    void                GrowExtents( OGREnvelope *psGeomBounds ); 
     139     
     140    KML*                GetKMLFile() { return poKMLFile; }; 
    137141     
    138142}; 
     
    157161 
    158162#endif /* OGR_KML_H_INCLUDED */ 
     163 
  • trunk/gdal/ogr/ogrsf_frmts/kml/ogrkmldatasource.cpp

    r10645 r12091  
    44 * Project:  KML Driver 
    55 * Purpose:  Implementation of OGRKMLDataSource class. 
    6  * Author:   Christopher Condit, condit@sdsc.edu 
     6 * Author:   Christopher Condit, condit@sdsc.edu; 
     7 *           Jens Oberender, j.obi@troja.net 
    78 * 
    89 ****************************************************************************** 
    910 * Copyright (c) 2006, Christopher Condit 
     11 *               2007, Jens Oberender 
    1012 * 
    1113 * Permission is hereby granted, free of charge, to any person obtaining a 
     
    3133#include "cpl_string.h" 
    3234#include "cpl_error.h" 
    33  
    34 /************************************************************************/ 
    35 /*                         OGRKMLDataSource()                         */ 
     35#include "cpl_minixml.h" 
     36 
     37/************************************************************************/ 
     38/*                         OGRKMLDataSource()                           */ 
    3639/************************************************************************/ 
    3740OGRKMLDataSource::OGRKMLDataSource() 
     
    4851 
    4952/************************************************************************/ 
    50 /*                        ~OGRKMLDataSource()                         */ 
     53/*                        ~OGRKMLDataSource()                           */ 
    5154/************************************************************************/ 
    5255OGRKMLDataSource::~OGRKMLDataSource() 
     
    7275    CPLFree( papoLayers ); 
    7376     
     77    if(this->poKMLFile != NULL) 
     78        delete this->poKMLFile; 
    7479} 
    7580 
     
    7984int OGRKMLDataSource::Open( const char * pszNewName, int bTestOpen ) 
    8085{ 
    81     FILE        *fp; 
    82     char        szHeader[1000];  
    83          
     86    int nCount; 
     87    OGRKMLLayer *poLayer; 
     88    OGRwkbGeometryType poGeotype; 
     89 
    8490    CPLAssert( NULL != pszNewName ); 
    8591 
    8692/* -------------------------------------------------------------------- */ 
    87 /*      Open the source file.                                           */ 
    88 /* -------------------------------------------------------------------- */ 
    89     fp = VSIFOpen( pszNewName, "r" ); 
    90     if( fp == NULL ) 
    91     { 
    92         if( !bTestOpen ) 
    93             CPLError( CE_Failure, CPLE_OpenFailed,  
    94                       "Failed to open KML file `%s'.",  
    95                       pszNewName ); 
    96  
    97         return FALSE; 
    98     } 
    99  
    100 /* -------------------------------------------------------------------- */ 
    101 /*      If we aren't sure it is KML, load a header chunk and check      */ 
    102 /*      for signs it is KML                                             */ 
    103 /* -------------------------------------------------------------------- */ 
    104     if( bTestOpen ) 
    105     { 
    106         VSIFRead( szHeader, 1, sizeof(szHeader), fp ); 
    107         szHeader[sizeof(szHeader)-1] = '\0'; 
    108                          
    109         if( szHeader[0] != '<'  
    110             || strstr(szHeader, "http://earth.google.com/kml/2.0") == NULL ) 
    111         {                        
    112             VSIFClose( fp ); 
    113             return FALSE; 
     93/*      Create a KML object and open the source file.                   */ 
     94/* -------------------------------------------------------------------- */ 
     95    this->poKMLFile = new KMLvector(); 
     96    if( !this->poKMLFile->open( pszNewName )) { 
     97        delete this->poKMLFile; 
     98        this->poKMLFile = NULL; 
     99        return FALSE; 
     100    } 
     101    this->pszName = CPLStrdup( pszNewName ); 
     102 
     103/* -------------------------------------------------------------------- */ 
     104/*      If we aren't sure it is KML, validate it by start parsing       */ 
     105/* -------------------------------------------------------------------- */ 
     106    if( bTestOpen && !poKMLFile->isValid()) 
     107    { 
     108        delete this->poKMLFile; 
     109        this->poKMLFile = NULL; 
     110        return FALSE; 
     111    } 
     112 
     113/* -------------------------------------------------------------------- */ 
     114/*      Prescan the KML file so we can later work with the structure    */ 
     115/* -------------------------------------------------------------------- */ 
     116    this->poKMLFile->parse(); 
     117 
     118/* -------------------------------------------------------------------- */ 
     119/*      Classify the nodes                                              */ 
     120/* -------------------------------------------------------------------- */ 
     121    this->poKMLFile->classifyNodes(); 
     122 
     123/* -------------------------------------------------------------------- */ 
     124/*      Eliminate the empty containers                                  */ 
     125/* -------------------------------------------------------------------- */ 
     126    this->poKMLFile->eliminateEmpty(); 
     127 
     128/* -------------------------------------------------------------------- */ 
     129/*      Find layers to use in the KML structure                         */ 
     130/* -------------------------------------------------------------------- */ 
     131    this->poKMLFile->findLayers(NULL); 
     132 
     133/* -------------------------------------------------------------------- */ 
     134/*      Print the structure                                             */ 
     135/* -------------------------------------------------------------------- */ 
     136    this->poKMLFile->print(3); 
     137 
     138    nLayers = this->poKMLFile->numLayers(); 
     139 
     140/* -------------------------------------------------------------------- */ 
     141/*      Allocate memory for the Layers                                  */ 
     142/* -------------------------------------------------------------------- */ 
     143    papoLayers = (OGRKMLLayer **) 
     144        CPLMalloc( sizeof(OGRKMLLayer *) * nLayers ); 
     145 
     146    OGRSpatialReference *poSRS = new OGRSpatialReference("GEOGCS[\"WGS 84\", " 
     147        "   DATUM[\"WGS_1984\"," 
     148        "       SPHEROID[\"WGS 84\",6378137,298.257223563," 
     149        "           AUTHORITY[\"EPSG\",\"7030\"]]," 
     150        "           AUTHORITY[\"EPSG\",\"6326\"]]," 
     151        "       PRIMEM[\"Greenwich\",0," 
     152        "           AUTHORITY[\"EPSG\",\"8901\"]]," 
     153        "       UNIT[\"degree\",0.01745329251994328," 
     154        "           AUTHORITY[\"EPSG\",\"9122\"]]," 
     155        "           AUTHORITY[\"EPSG\",\"4326\"]]"); 
     156 
     157/* -------------------------------------------------------------------- */ 
     158/*      Create the Layers and fill them                                 */ 
     159/* -------------------------------------------------------------------- */ 
     160    for(nCount = 0; nCount < nLayers; nCount++) { 
     161        CPLDebug("KML", "Loading Layer #%d", nCount); 
     162        if(!this->poKMLFile->selectLayer(nCount)) { 
     163            CPLError(CE_Failure, CPLE_AppDefined, 
     164                "There are no layers or a layer can not be found!"); 
     165            break; 
    114166        } 
    115     } 
    116      
    117         VSIFClose( fp ); 
    118          
    119         CPLError( CE_Failure, CPLE_AppDefined,  
    120               "Reading KML files is not currently supported\n"); 
    121  
     167 
     168        if(this->poKMLFile->getCurrentType() == Point) 
     169            poGeotype = wkbPoint; 
     170        else if(this->poKMLFile->getCurrentType() == LineString) 
     171            poGeotype = wkbLineString; 
     172        else if(this->poKMLFile->getCurrentType() == Polygon) 
     173            poGeotype = wkbPolygon; 
     174        else 
     175            poGeotype = wkbUnknown; 
     176 
     177/* -------------------------------------------------------------------- */ 
     178/*      Create the layer object.                                        */ 
     179/* -------------------------------------------------------------------- */ 
     180        std::string sName = this->poKMLFile->getCurrentName(); 
     181        if(sName.compare("") == 0) { 
     182            char *pszName = new char[10]; 
     183            snprintf(pszName, 10, "Layer #%d", nCount); 
     184            sName = pszName; 
     185            if(pszName != NULL) 
     186                delete pszName; 
     187        } 
     188 
     189        poLayer = new OGRKMLLayer( sName.c_str(), poSRS, FALSE, poGeotype, this ); 
     190 
     191        poLayer->SetLayerNumber(nCount); 
     192 
     193/* -------------------------------------------------------------------- */ 
     194/*      Add layer to data source layer list.                            */ 
     195/* -------------------------------------------------------------------- */ 
     196        papoLayers[nCount] = poLayer; 
     197    } 
     198     
     199    poSRS->Release(); 
     200     
    122201    return TRUE;         
    123 } 
    124  
    125 /************************************************************************/ 
    126 /*                         TranslateKMLSchema()                         */ 
    127 /************************************************************************/ 
    128 OGRKMLLayer *OGRKMLDataSource::TranslateKMLSchema( KMLFeatureClass *poClass ) 
    129 { 
    130     CPLAssert( NULL != poClass ); 
    131  
    132     OGRKMLLayer *poLayer; 
    133     poLayer = new OGRKMLLayer( poClass->GetName(), NULL, FALSE,  
    134                                wkbUnknown, this ); 
    135  
    136     return poLayer; 
    137202} 
    138203 
     
    211276 
    212277/* -------------------------------------------------------------------- */ 
    213 /*      Close the previous layer (if there is one open)         */ 
     278/*      Close the previous layer (if there is one open)                 */ 
    214279/* -------------------------------------------------------------------- */ 
    215280    if (GetLayerCount() > 0) 
     
    266331OGRLayer *OGRKMLDataSource::GetLayer( int iLayer ) 
    267332{ 
     333    CPLDebug("KML", "Get Layer #%d", iLayer); 
    268334    if( iLayer < 0 || iLayer >= nLayers ) 
    269335        return NULL; 
  • trunk/gdal/ogr/ogrsf_frmts/kml/ogrkmldriver.cpp

    r10645 r12091  
    44 * Project:  KML Driver 
    55 * Purpose:  Implementation of OGRKMLDriver class. 
    6  * Author:   Christopher Condit, condit@sdsc.edu 
     6 * Author:   Christopher Condit, condit@sdsc.edu; 
     7 *           Jens Oberender, j.obi@troja.net 
    78 * 
    89 ****************************************************************************** 
    910 * Copyright (c) 2006, Christopher Condit 
     11 *               2007, Jens Oberender 
    1012 * 
    1113 * Permission is hereby granted, free of charge, to any person obtaining a 
     
    6163    poDS = new OGRKMLDataSource(); 
    6264 
    63     if( !poDS->Open( pszFilename, TRUE ) 
    64         || poDS->GetLayerCount() == 0 ) 
     65    if( !poDS->Open( pszFilename, TRUE ) ) 
    6566    { 
     67        delete poDS; 
     68        return NULL; 
     69    } 
     70 
     71    if( poDS->GetLayerCount() == 0 ) 
     72    { 
     73        CPLError( CE_Failure, CPLE_OpenFailed,  
     74                  "No layers in KML file: `%s'.",  
     75                  pszFilename ); 
     76 
    6677        delete poDS; 
    6778        return NULL; 
     
    110121} 
    111122 
     123 
  • trunk/gdal/ogr/ogrsf_frmts/kml/ogrkmllayer.cpp

    r10645 r12091  
    55 * Purpose:  Implementation of OGRKMLLayer class. 
    66 * Author:   Christopher Condit, condit@sdsc.edu 
     7 *           Jens Oberender, j.obi@troja.net 
    78 * 
    89 ****************************************************************************** 
     
    3334#include "cpl_string.h" 
    3435 
    35 // Function utility to dump OGRGeoemtry to KML text 
     36/* Function utility to dump OGRGeoemtry to KML text. */ 
    3637char *OGR_G_ExportToKML( OGRGeometryH hGeometry ); 
    3738 
     
    4546{ 
    4647    if( poSRSIn == NULL ) 
    47         poSRS = NULL; 
     48        this->poSRS = NULL; 
    4849    else 
    49         poSRS = poSRSIn->Clone();         
    50      
    51     iNextKMLId = 0; 
    52     nTotalKMLCount = -1; 
    53      
    54     poDS = poDSIn; 
    55      
    56     poFeatureDefn = new OGRFeatureDefn( pszName ); 
    57     poFeatureDefn->Reference(); 
    58     poFeatureDefn->SetGeomType( eReqType ); 
    59  
    60     bWriter = bWriterIn; 
    61  
    62     poFClass = NULL;     
    63 
    64  
    65 /************************************************************************/ 
    66 /*                           ~OGRKMLLayer()                           */ 
     50        this->poSRS = poSRSIn->Clone();         
     51     
     52    this->iNextKMLId = 0; 
     53    this->nTotalKMLCount = -1; 
     54     
     55    this->poDS = poDSIn; 
     56     
     57    this->poFeatureDefn = new OGRFeatureDefn( pszName ); 
     58    this->poFeatureDefn->Reference(); 
     59    this->poFeatureDefn->SetGeomType( eReqType ); 
     60 
     61    OGRFieldDefn *oFieldTemplate = new OGRFieldDefn( "Name", OFTString ); 
     62    this->poFeatureDefn->AddFieldDefn( oFieldTemplate ); 
     63    delete oFieldTemplate; 
     64    oFieldTemplate = new OGRFieldDefn( "Description", OFTString ); 
     65    this->poFeatureDefn->AddFieldDefn( oFieldTemplate ); 
     66    delete oFieldTemplate; 
     67 
     68    this->bWriter = bWriterIn; 
     69 
     70
     71 
     72/************************************************************************/ 
     73/*                           ~OGRKMLLayer()                             */ 
    6774/************************************************************************/ 
    6875OGRKMLLayer::~OGRKMLLayer() 
     
    8895OGRFeature *OGRKMLLayer::GetNextFeature() 
    8996{ 
    90         CPLError( CE_Failure, CPLE_AppDefined,  
    91               "OGRKMLLayer::GetExtent: KML driver is write-only!\n"); 
    92  
    93     return NULL; 
     97    CPLDebug("KML", "GetNextFeature(#%d)", this->iNextKMLId); 
     98    Feature *poFeatureKML; 
     99    unsigned short nCount, nCount2; 
     100    KML *poKMLFile = poDS->GetKMLFile(); 
     101    poKMLFile->selectLayer(this->nLayerNumber); 
     102 
     103    poFeatureKML = poKMLFile->getFeature(this->iNextKMLId++); 
     104 
     105    if(poFeatureKML == NULL) 
     106        return NULL; 
     107    if(this->poFeatureDefn == NULL) 
     108        CPLDebug("KML", "Ohoh"); 
     109 
     110    OGRFeature *poFeature = new OGRFeature( this->poFeatureDefn ); 
     111     
     112    // Handle a Point 
     113    if(poFeatureKML->eType == Point) 
     114    { 
     115        poFeature->SetGeometryDirectly( 
     116                new OGRPoint( poFeatureKML->pvpsCoordinates->at(0)->dfLongitude, poFeatureKML->pvpsCoordinates->at(0)->dfLatitude, poFeatureKML->pvpsCoordinates->at(0)->dfAltitude) 
     117                ); 
     118    } 
     119    // Handle a LineString 
     120    else if(poFeatureKML->eType == LineString) 
     121    { 
     122        OGRLineString *poLS = new OGRLineString(); 
     123        for(nCount = 0; nCount < poFeatureKML->pvpsCoordinates->size(); nCount++) 
     124        { 
     125            poLS->addPoint(poFeatureKML->pvpsCoordinates->at(nCount)->dfLongitude, poFeatureKML->pvpsCoordinates->at(nCount)->dfLatitude, poFeatureKML->pvpsCoordinates->at(nCount)->dfAltitude); 
     126        } 
     127        poFeature->SetGeometryDirectly(poLS); 
     128    } 
     129    // Handle a Polygon 
     130    else if(poFeatureKML->eType == Polygon) 
     131    { 
     132        OGRPolygon *poPG = new OGRPolygon(); 
     133        OGRLinearRing *poLR = new OGRLinearRing(); 
     134        for(nCount = 0; nCount < poFeatureKML->pvpsCoordinates->size(); nCount++) 
     135        { 
     136            poLR->addPoint(poFeatureKML->pvpsCoordinates->at(nCount)->dfLongitude, poFeatureKML->pvpsCoordinates->at(nCount)->dfLatitude, poFeatureKML->pvpsCoordinates->at(nCount)->dfAltitude); 
     137        } 
     138        poPG->addRingDirectly(poLR); 
     139        for(nCount = 0; nCount < poFeatureKML->pvpsCoordinatesExtra->size(); nCount++) 
     140        { 
     141            poLR = new OGRLinearRing(); 
     142            for(nCount2 = 0; nCount2 < poFeatureKML->pvpsCoordinatesExtra->at(nCount)->size(); nCount2++) 
     143            { 
     144                poLR->addPoint(poFeatureKML->pvpsCoordinatesExtra->at(nCount)->at(nCount2)->dfLongitude,  
     145                    poFeatureKML->pvpsCoordinatesExtra->at(nCount)->at(nCount2)->dfLatitude,  
     146                    poFeatureKML->pvpsCoordinatesExtra->at(nCount)->at(nCount2)->dfAltitude); 
     147            } 
     148            poPG->addRingDirectly(poLR); 
     149        } 
     150        poFeature->SetGeometryDirectly(poPG); 
     151    } 
     152 
     153    // Add fields 
     154    poFeature->SetField( poFeatureDefn->GetFieldIndex("Name"), poFeatureKML->sName.c_str() ); 
     155    poFeature->SetField( poFeatureDefn->GetFieldIndex("Description"), poFeatureKML->sDescription.c_str() ); 
     156    poFeature->SetFID( this->nNextFID++ ); 
     157 
     158    // Clean up 
     159    for(nCount = 0; nCount < poFeatureKML->pvpsCoordinates->size(); nCount++) 
     160    { 
     161        delete poFeatureKML->pvpsCoordinates->at(nCount); 
     162    } 
     163 
     164    if(poFeatureKML->pvpsCoordinatesExtra != NULL) 
     165    { 
     166        for(nCount = 0; nCount < poFeatureKML->pvpsCoordinatesExtra->size(); nCount++) 
     167        { 
     168            for(nCount2 = 0; nCount2 < poFeatureKML->pvpsCoordinatesExtra->at(nCount)->size(); nCount2++) 
     169                delete poFeatureKML->pvpsCoordinatesExtra->at(nCount)->at(nCount2); 
     170            delete poFeatureKML->pvpsCoordinatesExtra->at(nCount); 
     171        } 
     172        delete poFeatureKML->pvpsCoordinatesExtra; 
     173    } 
     174 
     175    delete poFeatureKML->pvpsCoordinates; 
     176    delete poFeatureKML; 
     177 
     178    // Return the feature 
     179    return poFeature; 
    94180} 
    95181 
     
    99185int OGRKMLLayer::GetFeatureCount( int bForce ) 
    100186{ 
    101     if( poFClass == NULL ) 
    102         return 0; 
    103  
    104     if( m_poFilterGeom != NULL || m_poAttrQuery != NULL ) 
    105         return OGRLayer::GetFeatureCount( bForce ); 
    106     else 
    107         return poFClass->GetFeatureCount(); 
     187    KML *poKMLFile = poDS->GetKMLFile(); 
     188    poKMLFile->selectLayer(this->nLayerNumber); 
     189 
     190    return poKMLFile->getNumFeatures(); 
    108191} 
    109192 
     
    115198    CPLAssert( NULL != psExtent ); 
    116199 
    117         CPLError( CE_Failure, CPLE_AppDefined,  
    118               "OGRKMLLayer::GetExtent: KML driver is write-only!\n"); 
    119  
    120     return OGRERR_NONE;  
     200    double dfXMin, dfXMax, dfYMin, dfYMax; 
     201 
     202    KML *poKMLFile = poDS->GetKMLFile(); 
     203    poKMLFile->selectLayer(this->nLayerNumber); 
     204 
     205    if(poKMLFile->getExtents( &dfXMin, &dfXMax, &dfYMin, &dfYMax )) 
     206    { 
     207        psExtent->MinX = dfXMin; 
     208        psExtent->MaxX = dfXMax; 
     209        psExtent->MinY = dfYMin; 
     210        psExtent->MaxY = dfYMax; 
     211 
     212        return OGRERR_NONE; 
     213    } 
     214    else  
     215        return OGRERR_FAILURE; 
    121216} 
    122217 
     
    126221OGRErr OGRKMLLayer::CreateFeature( OGRFeature *poFeature ) 
    127222{ 
    128     FILE        *fp = poDS->GetOutputFP(); 
     223    FILE *fp = poDS->GetOutputFP(); 
    129224 
    130225    if( !bWriter ) 
     
    144239            OGRFieldDefn *poField = poFeatureDefn->GetFieldDefn( iField ); 
    145240 
    146             if ( poFeature->IsFieldSet( iField ) &&  
    147                 !strcmp(poField->GetNameRef(), poDS->GetNameField())
     241            if( poFeature->IsFieldSet( iField ) 
     242                && !strcmp(poField->GetNameRef(), poDS->GetNameField())
    148243            {            
    149244                const char *pszRaw = poFeature->GetFieldAsString( iField ); 
     
    160255     
    161256        VSIFPrintf( fp, "    <description><![CDATA[\n" ); 
     257 
    162258    // Write all "set" fields that aren't being used for the name element 
    163259    for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ ) 
     
    227323    else if( EQUAL(pszCap,OLCFastGetExtent) ) 
    228324    { 
    229         double  dfXMin, dfXMax, dfYMin, dfYMax; 
    230  
    231         if( poFClass == NULL ) 
     325//        double  dfXMin, dfXMax, dfYMin, dfYMax; 
     326 
     327//        if( poFClass == NULL ) 
    232328            return FALSE; 
    233329 
    234         return poFClass->GetExtents( &dfXMin, &dfXMax, &dfYMin, &dfYMax ); 
     330//        return poFClass->GetExtents( &dfXMin, &dfXMax, &dfYMin, &dfYMax ); 
    235331    } 
    236332 
    237333    else if( EQUAL(pszCap,OLCFastFeatureCount) ) 
    238334    { 
    239         if( poFClass == NULL  
    240             || m_poFilterGeom != NULL  
    241             || m_poAttrQuery != NULL ) 
     335//        if( poFClass == NULL  
     336//            || m_poFilterGeom != NULL  
     337//            || m_poAttrQuery != NULL ) 
    242338            return FALSE; 
    243339 
    244         return poFClass->GetFeatureCount() != -1; 
     340//        return poFClass->GetFeatureCount() != -1; 
    245341    } 
    246342 
     
    271367} 
    272368 
     369/************************************************************************/ 
     370/*                           SetLayerNumber()                           */ 
     371/************************************************************************/ 
     372void OGRKMLLayer::SetLayerNumber(unsigned short nNum) 
     373{ 
     374    this->nLayerNumber = nNum; 
     375} 
     376 
     377