OGRLIBKMLLayer::OGRLIBKMLLayer( const char *pszLayerName, OGRSpatialReference * poSpatialRef, OGRwkbGeometryType eGType, OGRLIBKMLDataSource * poOgrDS, ElementPtr poKmlRoot, ContainerPtr poKmlContainer, UpdatePtr poKmlUpdate, const char *pszFileName, int bNew, int bUpdateIn ) : bUpdate(CPL_TO_BOOL(bUpdateIn)), bUpdated(false), nFeatures(0), iFeature(0), nFID(1), m_pszName(CPLStrdup(pszLayerName)), m_pszFileName(CPLStrdup(pszFileName)), m_poKmlLayer(poKmlContainer), // Store the layers container. m_poKmlLayerRoot(poKmlRoot), // Store the root element pointer. m_poKmlUpdate(poKmlUpdate), m_poOgrDS(poOgrDS), m_poOgrFeatureDefn(new OGRFeatureDefn(pszLayerName)), m_poKmlSchema(NULL), m_poOgrSRS(new OGRSpatialReference(NULL)), m_bReadGroundOverlay(CPLTestBool( CPLGetConfigOption("LIBKML_READ_GROUND_OVERLAY", "YES"))), m_bUseSimpleField(CPLTestBool( CPLGetConfigOption("LIBKML_USE_SIMPLEFIELD", "YES"))), m_bWriteRegion(false), m_bRegionBoundsAuto(false), m_dfRegionMinLodPixels(0), m_dfRegionMaxLodPixels(-1), m_dfRegionMinFadeExtent(0), m_dfRegionMaxFadeExtent(0), m_dfRegionMinX(200), m_dfRegionMinY(200), m_dfRegionMaxX(-200), m_dfRegionMaxY(-200), m_bUpdateIsFolder(false) { m_poStyleTable = NULL; m_poOgrSRS->SetWellKnownGeogCS( "WGS84" ); SetDescription( m_poOgrFeatureDefn->GetName() ); m_poOgrFeatureDefn->Reference(); m_poOgrFeatureDefn->SetGeomType( eGType ); if( m_poOgrFeatureDefn->GetGeomFieldCount() != 0 ) m_poOgrFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(m_poOgrSRS); /***** was the layer created from a DS::Open *****/ if( !bNew ) { /***** get the number of features on the layer *****/ nFeatures = static_cast<int>(m_poKmlLayer->get_feature_array_size()); /***** get the field config *****/ struct fieldconfig oFC; get_fieldconfig( &oFC ); /***** name field *****/ OGRFieldDefn oOgrFieldName( oFC.namefield,OFTString ); m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldName ); /***** description field *****/ OGRFieldDefn oOgrFieldDesc( oFC.descfield, OFTString ); m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldDesc ); /***** timestamp field *****/ OGRFieldDefn oOgrFieldTs( oFC.tsfield, OFTDateTime ); m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldTs ); /***** timespan begin field *****/ OGRFieldDefn oOgrFieldBegin( oFC.beginfield, OFTDateTime ); m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldBegin ); /***** timespan end field *****/ OGRFieldDefn oOgrFieldEnd( oFC.endfield, OFTDateTime ); m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldEnd ); /***** altitudeMode field *****/ OGRFieldDefn oOgrFieldAltitudeMode( oFC.altitudeModefield, OFTString ); m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldAltitudeMode ); /***** tessellate field *****/ OGRFieldDefn oOgrFieldTessellate( oFC.tessellatefield, OFTInteger ); m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldTessellate ); /***** extrude field *****/ OGRFieldDefn oOgrFieldExtrude( oFC.extrudefield, OFTInteger ); m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldExtrude ); /***** visibility field *****/ OGRFieldDefn oOgrFieldVisibility( oFC.visibilityfield, OFTInteger ); m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldVisibility ); /***** draw order field *****/ OGRFieldDefn oOgrFieldDrawOrder( oFC.drawOrderfield, OFTInteger ); m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldDrawOrder ); /***** icon field *****/ OGRFieldDefn oOgrFieldIcon( oFC.iconfield, OFTString ); m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldIcon ); /***** get the styles *****/ if( m_poKmlLayer->IsA( kmldom::Type_Document ) ) ParseStyles( AsDocument ( m_poKmlLayer ), &m_poStyleTable ); /***** get the schema if the layer is a Document *****/ if( m_poKmlLayer->IsA( kmldom::Type_Document ) ) { DocumentPtr poKmlDocument = AsDocument( m_poKmlLayer ); if( poKmlDocument->get_schema_array_size() ) { m_poKmlSchema = poKmlDocument->get_schema_array_at( 0 ); kml2FeatureDef( m_poKmlSchema, m_poOgrFeatureDefn ); } } /***** the schema is somewhere else *****/ if( m_poKmlSchema == NULL ) { /***** try to find the correct schema *****/ bool bHasHeading = false; bool bHasTilt = false; bool bHasRoll = false; bool bHasSnippet = false; FeaturePtr poKmlFeature = NULL; /***** find the first placemark *****/ do { if( iFeature >= nFeatures ) break; poKmlFeature = m_poKmlLayer->get_feature_array_at( iFeature++ ); if( poKmlFeature->Type() == kmldom::Type_Placemark ) { PlacemarkPtr poKmlPlacemark = AsPlacemark( poKmlFeature ); if( !poKmlPlacemark->has_geometry() && poKmlPlacemark->has_abstractview() && poKmlPlacemark->get_abstractview()-> IsA( kmldom::Type_Camera) ) { const CameraPtr& camera = AsCamera(poKmlPlacemark->get_abstractview()); if( camera->has_heading() && !bHasHeading ) { bHasHeading = true; OGRFieldDefn oOgrField( oFC.headingfield, OFTReal ); m_poOgrFeatureDefn->AddFieldDefn( &oOgrField ); } if( camera->has_tilt() && !bHasTilt ) { bHasTilt = true; OGRFieldDefn oOgrField( oFC.tiltfield, OFTReal ); m_poOgrFeatureDefn->AddFieldDefn( &oOgrField ); } if( camera->has_roll() && !bHasRoll ) { bHasRoll = true; OGRFieldDefn oOgrField( oFC.rollfield, OFTReal ); m_poOgrFeatureDefn->AddFieldDefn( &oOgrField ); } } } if( !bHasSnippet && poKmlFeature->has_snippet() ) { bHasSnippet = true; OGRFieldDefn oOgrField( oFC.snippetfield, OFTString ); m_poOgrFeatureDefn->AddFieldDefn( &oOgrField ); } } while( poKmlFeature->Type() != kmldom::Type_Placemark ); if( iFeature <= nFeatures && poKmlFeature && poKmlFeature->Type() == kmldom::Type_Placemark && poKmlFeature->has_extendeddata() ) { const ExtendedDataPtr poKmlExtendedData = poKmlFeature->get_extendeddata(); if( poKmlExtendedData->get_schemadata_array_size() > 0 ) { const SchemaDataPtr poKmlSchemaData = poKmlExtendedData->get_schemadata_array_at( 0 ); if( poKmlSchemaData->has_schemaurl() ) { std::string oKmlSchemaUrl = poKmlSchemaData->get_schemaurl(); if( ( m_poKmlSchema = m_poOgrDS->FindSchema( oKmlSchemaUrl.c_str() ) ) ) { kml2FeatureDef( m_poKmlSchema, m_poOgrFeatureDefn ); } } } else if( poKmlExtendedData->get_data_array_size() > 0 ) { // Use the <Data> of the first placemark to build the // feature definition. If others have different fields, // too bad... const bool bLaunderFieldNames = CPLTestBool(CPLGetConfigOption( "LIBKML_LAUNDER_FIELD_NAMES", "YES")); const size_t nDataArraySize = poKmlExtendedData->get_data_array_size(); for( size_t i = 0; i < nDataArraySize; i++ ) { const DataPtr& data = poKmlExtendedData->get_data_array_at(i); if( data->has_name() ) { CPLString osName = std::string(data->get_name()); if( bLaunderFieldNames ) osName = LaunderFieldNames(osName); OGRFieldDefn oOgrField( osName, OFTString ); m_poOgrFeatureDefn->AddFieldDefn( &oOgrField ); } } } } iFeature = 0; } /***** check if any features are another layer *****/ m_poOgrDS->ParseLayers( m_poKmlLayer, poSpatialRef ); } /***** it was from a DS::CreateLayer *****/ else { /***** mark the layer as updated *****/ bUpdated = true; } }