OGRLIBKMLLayer::OGRLIBKMLLayer ( const char *pszLayerName, OGRSpatialReference * poSpatialRef, OGRwkbGeometryType eGType, OGRLIBKMLDataSource * poOgrDS, ElementPtr poKmlRoot, ContainerPtr poKmlContainer, UpdatePtr poKmlUpdate, const char *pszFileName, int bNew, int bUpdateIn ) { m_poStyleTable = NULL; iFeature = 0; nFeatures = 0; nFID = 1; this->bUpdate = bUpdateIn; bUpdated = FALSE; m_pszName = CPLStrdup ( pszLayerName ); m_pszFileName = CPLStrdup ( pszFileName ); m_poOgrDS = poOgrDS; m_poOgrSRS = new OGRSpatialReference ( NULL ); m_poOgrSRS->SetWellKnownGeogCS ( "WGS84" ); m_poOgrFeatureDefn = new OGRFeatureDefn ( pszLayerName ); SetDescription( m_poOgrFeatureDefn->GetName() ); m_poOgrFeatureDefn->Reference ( ); m_poOgrFeatureDefn->SetGeomType ( eGType ); if( m_poOgrFeatureDefn->GetGeomFieldCount() != 0 ) m_poOgrFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(m_poOgrSRS); /***** store the root element pointer *****/ m_poKmlLayerRoot = poKmlRoot; /***** store the layers container *****/ m_poKmlLayer = poKmlContainer; /* update container */ m_poKmlUpdate = poKmlUpdate; m_poKmlSchema = NULL; /***** related to Region *****/ 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_bReadGroundOverlay = CPLTestBool( CPLGetConfigOption("LIBKML_READ_GROUND_OVERLAY", "YES")); m_bUseSimpleField = CPLTestBool( CPLGetConfigOption("LIBKML_USE_SIMPLEFIELD", "YES")); m_bUpdateIsFolder = FALSE; /***** 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 *****/ int bHasHeading = FALSE, bHasTilt = FALSE, bHasRoll = FALSE; int bHasSnippet = FALSE; FeaturePtr poKmlFeature; /***** 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 ( ) ) { ExtendedDataPtr poKmlExtendedData = poKmlFeature-> get_extendeddata ( ); if ( poKmlExtendedData->get_schemadata_array_size ( ) > 0 ) { 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... */ int bLaunderFieldNames = CPLTestBool(CPLGetConfigOption("LIBKML_LAUNDER_FIELD_NAMES", "YES")); 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 = 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; } }
void kml2field ( OGRFeature * poOgrFeat, PlacemarkPtr poKmlPlacemark ) { const char *namefield = CPLGetConfigOption ( "LIBKML_NAME_FIELD", "Name" ); const char *descfield = CPLGetConfigOption ( "LIBKML_DESCRIPTION_FIELD", "description" ); const char *tsfield = CPLGetConfigOption ( "LIBKML_TIMESTAMP_FIELD", "timestamp" ); const char *beginfield = CPLGetConfigOption ( "LIBKML_BEGIN_FIELD", "begin" ); const char *endfield = CPLGetConfigOption ( "LIBKML_END_FIELD", "end" ); const char *altitudeModefield = CPLGetConfigOption ( "LIBKML_ALTITUDEMODE_FIELD", "altitudeMode" ); const char *tessellatefield = CPLGetConfigOption ( "LIBKML_TESSELLATE_FIELD", "tessellate" ); const char *extrudefield = CPLGetConfigOption ( "LIBKML_EXTRUDE_FIELD", "extrude" ); const char *visibilityfield = CPLGetConfigOption ( "LIBKML_VISIBILITY_FIELD", "visibility" ); /***** name *****/ if ( poKmlPlacemark->has_name ( ) ) { const std::string oKmlName = poKmlPlacemark->get_name ( ); int iField = poOgrFeat->GetFieldIndex ( namefield ); if ( iField > -1 ) poOgrFeat->SetField ( iField, oKmlName.c_str ( ) ); } /***** description *****/ if ( poKmlPlacemark->has_description ( ) ) { const std::string oKmlDesc = poKmlPlacemark->get_description ( ); int iField = poOgrFeat->GetFieldIndex ( descfield ); if ( iField > -1 ) poOgrFeat->SetField ( iField, oKmlDesc.c_str ( ) ); } if ( poKmlPlacemark->has_timeprimitive ( ) ) { TimePrimitivePtr poKmlTimePrimitive = poKmlPlacemark->get_timeprimitive ( ); /***** timestamp *****/ if ( poKmlTimePrimitive->IsA ( kmldom::Type_TimeStamp ) ) { TimeStampPtr poKmlTimeStamp = AsTimeStamp ( poKmlTimePrimitive ); if ( poKmlTimeStamp->has_when ( ) ) { const std::string oKmlWhen = poKmlTimeStamp->get_when ( ); int iField = poOgrFeat->GetFieldIndex ( tsfield ); if ( iField > -1 ) { int nYear, nMonth, nDay, nHour, nMinute, nTZ; float fSecond; if ( OGRParseXMLDateTime ( oKmlWhen.c_str ( ), &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond, &nTZ ) ) poOgrFeat->SetField ( iField, nYear, nMonth, nDay, nHour, nMinute, ( int )fSecond, nTZ ); } } } /***** timespan *****/ if ( poKmlTimePrimitive->IsA ( kmldom::Type_TimeSpan ) ) { TimeSpanPtr poKmlTimeSpan = AsTimeSpan ( poKmlTimePrimitive ); /***** begin *****/ if ( poKmlTimeSpan->has_begin ( ) ) { const std::string oKmlWhen = poKmlTimeSpan->get_begin ( ); int iField = poOgrFeat->GetFieldIndex ( beginfield ); if ( iField > -1 ) { int nYear, nMonth, nDay, nHour, nMinute, nTZ; float fSecond; if ( OGRParseXMLDateTime ( oKmlWhen.c_str ( ), &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond, &nTZ ) ) poOgrFeat->SetField ( iField, nYear, nMonth, nDay, nHour, nMinute, ( int )fSecond, nTZ ); } } /***** end *****/ if ( poKmlTimeSpan->has_end ( ) ) { const std::string oKmlWhen = poKmlTimeSpan->get_end ( ); int iField = poOgrFeat->GetFieldIndex ( endfield ); if ( iField > -1 ) { int nYear, nMonth, nDay, nHour, nMinute, nTZ; float fSecond; if ( OGRParseXMLDateTime ( oKmlWhen.c_str ( ), &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond, &nTZ ) ) poOgrFeat->SetField ( iField, nYear, nMonth, nDay, nHour, nMinute, ( int )fSecond, nTZ ); } } } } if ( poKmlPlacemark->has_geometry ( ) ) { GeometryPtr poKmlGeometry = poKmlPlacemark->get_geometry ( ); /***** altitudeMode *****/ int bIsGX = FALSE; int nAltitudeMode = -1; int iField = poOgrFeat->GetFieldIndex ( altitudeModefield ); if ( iField > -1 ) { if ( kml2altitudemode_rec ( poKmlGeometry, &nAltitudeMode, &bIsGX ) ) { if ( !bIsGX ) { switch ( nAltitudeMode ) { case kmldom::ALTITUDEMODE_CLAMPTOGROUND: poOgrFeat->SetField ( iField, "clampToGround" ); break; case kmldom::ALTITUDEMODE_RELATIVETOGROUND: poOgrFeat->SetField ( iField, "relativeToGround" ); break; case kmldom::ALTITUDEMODE_ABSOLUTE: poOgrFeat->SetField ( iField, "absolute" ); break; } } else { switch ( nAltitudeMode ) { case kmldom::GX_ALTITUDEMODE_RELATIVETOSEAFLOOR: poOgrFeat->SetField ( iField, "relativeToSeaFloor" ); break; case kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR: poOgrFeat->SetField ( iField, "clampToSeaFloor" ); break; } } } } /***** tessellate *****/ int nTessellate = -1; kml2tessellate_rec ( poKmlGeometry, &nTessellate ); iField = poOgrFeat->GetFieldIndex ( tessellatefield ); if ( iField > -1 ) poOgrFeat->SetField ( iField, nTessellate ); /***** extrude *****/ int nExtrude = -1; kml2extrude_rec ( poKmlGeometry, &nExtrude ); iField = poOgrFeat->GetFieldIndex ( extrudefield ); if ( iField > -1 ) poOgrFeat->SetField ( iField, nExtrude ); } /***** visibility *****/ int nVisibility = -1; if ( poKmlPlacemark->has_visibility ( ) ) nVisibility = poKmlPlacemark->get_visibility ( ); int iField = poOgrFeat->GetFieldIndex ( visibilityfield ); if ( iField > -1 ) poOgrFeat->SetField ( iField, nVisibility ); ExtendedDataPtr poKmlExtendedData = NULL; if ( poKmlPlacemark->has_extendeddata ( ) ) { poKmlExtendedData = poKmlPlacemark->get_extendeddata ( ); /***** loop over the schemadata_arrays *****/ size_t nSchemaData = poKmlExtendedData->get_schemadata_array_size ( ); size_t iSchemaData; for ( iSchemaData = 0; iSchemaData < nSchemaData; iSchemaData++ ) { SchemaDataPtr poKmlSchemaData = poKmlExtendedData->get_schemadata_array_at ( iSchemaData ); /***** loop over the simpledata array *****/ size_t nSimpleData = poKmlSchemaData->get_simpledata_array_size ( ); size_t iSimpleData; for ( iSimpleData = 0; iSimpleData < nSimpleData; iSimpleData++ ) { SimpleDataPtr poKmlSimpleData = poKmlSchemaData->get_simpledata_array_at ( iSimpleData ); /***** find the field index *****/ int iField = -1; if ( poKmlSimpleData->has_name ( ) ) { const string oName = poKmlSimpleData->get_name ( ); const char *pszName = oName.c_str ( ); iField = poOgrFeat->GetFieldIndex ( pszName ); } /***** if it has trxt set the field *****/ if ( iField > -1 && poKmlSimpleData->has_text ( ) ) { string oText = poKmlSimpleData->get_text ( ); /* SerializePretty() adds a new line before the data */ /* ands trailing spaces. I believe this is wrong */ /* as it breaks round-tripping */ /* Trim trailing spaces */ while (oText.size() != 0 && oText[oText.size()-1] == ' ') oText.resize(oText.size()-1); /* Skip leading newline and spaces */ const char* pszText = oText.c_str ( ); if (pszText[0] == '\n') pszText ++; while (pszText[0] == ' ') pszText ++; poOgrFeat->SetField ( iField, pszText ); } } } if (nSchemaData == 0 && poKmlExtendedData->get_data_array_size() > 0 ) { int bLaunderFieldNames = CSLTestBoolean(CPLGetConfigOption("LIBKML_LAUNDER_FIELD_NAMES", "YES")); 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() && data->has_value()) { CPLString osName = data->get_name(); if (bLaunderFieldNames) osName = OGRLIBKMLLayer::LaunderFieldNames(osName); int iField = poOgrFeat->GetFieldIndex ( osName ); if (iField >= 0) { poOgrFeat->SetField ( iField, data->get_value().c_str() ); } } } } } }
OGRLIBKMLLayer::OGRLIBKMLLayer( const char *pszLayerName, OGRwkbGeometryType eGType, OGRLIBKMLDataSource * poOgrDS, ElementPtr poKmlRoot, ContainerPtr poKmlContainer, UpdatePtr poKmlUpdate, const char *pszFileName, int bNew, int bUpdateIn ) : bUpdate(CPL_TO_BOOL(bUpdateIn)), 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(nullptr), m_poOgrSRS(new OGRSpatialReference(nullptr)), 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 = nullptr; m_poOgrSRS->SetWellKnownGeogCS( "WGS84" ); m_poOgrSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); 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 ); bool bCanSetKmlSchema = true; /***** 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() ) { for(size_t i = 0; i < poKmlDocument->get_schema_array_size(); i++ ) { auto schema = poKmlDocument->get_schema_array_at( i ); if( bCanSetKmlSchema && !m_poKmlSchema ) { m_poKmlSchema = schema; bCanSetKmlSchema = false; } else { m_poKmlSchema = nullptr; } kml2FeatureDef( schema, m_poOgrFeatureDefn ); } } } /***** the schema is somewhere else *****/ if( bCanSetKmlSchema ) { /***** try to find the correct schema *****/ bool bHasHeading = false; bool bHasTilt = false; bool bHasRoll = false; bool bHasSnippet = false; FeaturePtr poKmlFeature = nullptr; const bool bLaunderFieldNames = CPLTestBool(CPLGetConfigOption( "LIBKML_LAUNDER_FIELD_NAMES", "YES")); std::set<std::string> oSetSchemaAlreadyVisited; /***** find the first placemark *****/ for( iFeature = 0; iFeature < nFeatures; iFeature++ ) { 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( 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( oSetSchemaAlreadyVisited.find( oKmlSchemaUrl) == oSetSchemaAlreadyVisited.end() ) { oSetSchemaAlreadyVisited.insert( oKmlSchemaUrl); auto schema = m_poOgrDS->FindSchema( oKmlSchemaUrl.c_str() ); if( schema ) { if( bCanSetKmlSchema && !m_poKmlSchema ) { m_poKmlSchema = schema; bCanSetKmlSchema = false; } else { m_poKmlSchema = nullptr; } kml2FeatureDef( schema, m_poOgrFeatureDefn ); } } } } else if( poKmlExtendedData->get_data_array_size() > 0 ) { 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); if( m_poOgrFeatureDefn->GetFieldIndex(osName) < 0 ) { OGRFieldDefn oOgrField( osName, OFTString ); m_poOgrFeatureDefn->AddFieldDefn( &oOgrField ); } } } } } } if( !bHasSnippet && poKmlFeature->has_snippet() ) { bHasSnippet = true; OGRFieldDefn oOgrField( oFC.snippetfield, OFTString ); m_poOgrFeatureDefn->AddFieldDefn( &oOgrField ); } } iFeature = 0; } } }
void field2kml ( OGRFeature * poOgrFeat, OGRLIBKMLLayer * poOgrLayer, KmlFactory * poKmlFactory, PlacemarkPtr poKmlPlacemark ) { int i; SchemaDataPtr poKmlSchemaData = poKmlFactory->CreateSchemaData ( ); SchemaPtr poKmlSchema = poOgrLayer->GetKmlSchema ( ); /***** set the url to the schema *****/ if ( poKmlSchema && poKmlSchema->has_id ( ) ) { std::string oKmlSchemaID = poKmlSchema->get_id ( ); std::string oKmlSchemaURL = "#"; oKmlSchemaURL.append ( oKmlSchemaID ); poKmlSchemaData->set_schemaurl ( oKmlSchemaURL ); } const char *namefield = CPLGetConfigOption ( "LIBKML_NAME_FIELD", "Name" ); const char *descfield = CPLGetConfigOption ( "LIBKML_DESCRIPTION_FIELD", "description" ); const char *tsfield = CPLGetConfigOption ( "LIBKML_TIMESTAMP_FIELD", "timestamp" ); const char *beginfield = CPLGetConfigOption ( "LIBKML_BEGIN_FIELD", "begin" ); const char *endfield = CPLGetConfigOption ( "LIBKML_END_FIELD", "end" ); const char *altitudeModefield = CPLGetConfigOption ( "LIBKML_ALTITUDEMODE_FIELD", "altitudeMode" ); const char *tessellatefield = CPLGetConfigOption ( "LIBKML_TESSELLATE_FIELD", "tessellate" ); const char *extrudefield = CPLGetConfigOption ( "LIBKML_EXTRUDE_FIELD", "extrude" ); const char *visibilityfield = CPLGetConfigOption ( "LIBKML_VISIBILITY_FIELD", "visibility" ); TimeSpanPtr poKmlTimeSpan = NULL; int nFields = poOgrFeat->GetFieldCount ( ); int iSkip1 = -1; int iSkip2 = -1; for ( i = 0; i < nFields; i++ ) { /***** if the field is set to skip, do so *****/ if ( i == iSkip1 || i == iSkip2 ) continue; /***** if the field isn't set just bail now *****/ if ( !poOgrFeat->IsFieldSet ( i ) ) continue; OGRFieldDefn *poOgrFieldDef = poOgrFeat->GetFieldDefnRef ( i ); OGRFieldType type = poOgrFieldDef->GetType ( ); const char *name = poOgrFieldDef->GetNameRef ( ); SimpleDataPtr poKmlSimpleData = NULL; int year, month, day, hour, min, sec, tz; switch ( type ) { case OFTString: // String of ASCII chars { char* pszUTF8String = OGRLIBKMLSanitizeUTF8String( poOgrFeat->GetFieldAsString ( i )); /***** name *****/ if ( EQUAL ( name, namefield ) ) { poKmlPlacemark->set_name ( pszUTF8String ); CPLFree( pszUTF8String ); continue; } /***** description *****/ else if ( EQUAL ( name, descfield ) ) { poKmlPlacemark->set_description ( pszUTF8String ); CPLFree( pszUTF8String ); continue; } /***** altitudemode *****/ else if ( EQUAL ( name, altitudeModefield ) ) { const char *pszAltitudeMode = pszUTF8String ; int isGX = FALSE; int iAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND; if ( EQUAL ( pszAltitudeMode, "clampToGround" ) ) iAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND; else if ( EQUAL ( pszAltitudeMode, "relativeToGround" ) ) iAltitudeMode = kmldom::ALTITUDEMODE_RELATIVETOGROUND; else if ( EQUAL ( pszAltitudeMode, "absolute" ) ) iAltitudeMode = kmldom::ALTITUDEMODE_ABSOLUTE; else if ( EQUAL ( pszAltitudeMode, "relativeToSeaFloor" ) ) { iAltitudeMode = kmldom::GX_ALTITUDEMODE_RELATIVETOSEAFLOOR; isGX = TRUE; } else if ( EQUAL ( pszAltitudeMode, "clampToSeaFloor" ) ) { iAltitudeMode = kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR; isGX = TRUE; } if ( poKmlPlacemark->has_geometry ( ) ) { GeometryPtr poKmlGeometry = poKmlPlacemark->get_geometry ( ); ogr2altitudemode_rec ( poKmlGeometry, iAltitudeMode, isGX ); } CPLFree( pszUTF8String ); continue; } /***** timestamp *****/ else if ( EQUAL ( name, tsfield ) ) { TimeStampPtr poKmlTimeStamp = poKmlFactory->CreateTimeStamp ( ); poKmlTimeStamp->set_when ( pszUTF8String ); poKmlPlacemark->set_timeprimitive ( poKmlTimeStamp ); CPLFree( pszUTF8String ); continue; } /***** begin *****/ if ( EQUAL ( name, beginfield ) ) { if ( !poKmlTimeSpan ) { poKmlTimeSpan = poKmlFactory->CreateTimeSpan ( ); poKmlPlacemark->set_timeprimitive ( poKmlTimeSpan ); } poKmlTimeSpan->set_begin ( pszUTF8String ); CPLFree( pszUTF8String ); continue; } /***** end *****/ else if ( EQUAL ( name, endfield ) ) { if ( !poKmlTimeSpan ) { poKmlTimeSpan = poKmlFactory->CreateTimeSpan ( ); poKmlPlacemark->set_timeprimitive ( poKmlTimeSpan ); } poKmlTimeSpan->set_end ( pszUTF8String ); CPLFree( pszUTF8String ); continue; } /***** other *****/ poKmlSimpleData = poKmlFactory->CreateSimpleData ( ); poKmlSimpleData->set_name ( name ); poKmlSimpleData->set_text ( pszUTF8String ); CPLFree( pszUTF8String ); break; } case OFTDate: // Date { poOgrFeat->GetFieldAsDateTime ( i, &year, &month, &day, &hour, &min, &sec, &tz ); int iTimeField; for ( iTimeField = i + 1; iTimeField < nFields; iTimeField++ ) { if ( iTimeField == iSkip1 || iTimeField == iSkip2 ) continue; OGRFieldDefn *poOgrFieldDef2 = poOgrFeat->GetFieldDefnRef ( i ); OGRFieldType type2 = poOgrFieldDef2->GetType ( ); const char *name2 = poOgrFieldDef2->GetNameRef ( ); if ( EQUAL ( name2, name ) && type2 == OFTTime && ( EQUAL ( name, tsfield ) || EQUAL ( name, beginfield ) || EQUAL ( name, endfield ) ) ) { int year2, month2, day2, hour2, min2, sec2, tz2; poOgrFeat->GetFieldAsDateTime ( iTimeField, &year2, &month2, &day2, &hour2, &min2, &sec2, &tz2 ); hour = hour2; min = min2; sec = sec2; tz = tz2; if ( 0 > iSkip1 ) iSkip1 = iTimeField; else iSkip2 = iTimeField; } } goto Do_DateTime; } case OFTTime: // Time { poOgrFeat->GetFieldAsDateTime ( i, &year, &month, &day, &hour, &min, &sec, &tz ); int iTimeField; for ( iTimeField = i + 1; iTimeField < nFields; iTimeField++ ) { if ( iTimeField == iSkip1 || iTimeField == iSkip2 ) continue; OGRFieldDefn *poOgrFieldDef2 = poOgrFeat->GetFieldDefnRef ( i ); OGRFieldType type2 = poOgrFieldDef2->GetType ( ); const char *name2 = poOgrFieldDef2->GetNameRef ( ); if ( EQUAL ( name2, name ) && type2 == OFTTime && ( EQUAL ( name, tsfield ) || EQUAL ( name, beginfield ) || EQUAL ( name, endfield ) ) ) { int year2, month2, day2, hour2, min2, sec2, tz2; poOgrFeat->GetFieldAsDateTime ( iTimeField, &year2, &month2, &day2, &hour2, &min2, &sec2, &tz2 ); year = year2; month = month2; day = day2; if ( 0 > iSkip1 ) iSkip1 = iTimeField; else iSkip2 = iTimeField; } } goto Do_DateTime; } case OFTDateTime: // Date and Time { poOgrFeat->GetFieldAsDateTime ( i, &year, &month, &day, &hour, &min, &sec, &tz ); Do_DateTime: /***** timestamp *****/ if ( EQUAL ( name, tsfield ) ) { char *timebuf = OGRGetXMLDateTime ( year, month, day, hour, min, sec, tz ); TimeStampPtr poKmlTimeStamp = poKmlFactory->CreateTimeStamp ( ); poKmlTimeStamp->set_when ( timebuf ); poKmlPlacemark->set_timeprimitive ( poKmlTimeStamp ); CPLFree( timebuf ); continue; } /***** begin *****/ if ( EQUAL ( name, beginfield ) ) { char *timebuf = OGRGetXMLDateTime ( year, month, day, hour, min, sec, tz ); if ( !poKmlTimeSpan ) { poKmlTimeSpan = poKmlFactory->CreateTimeSpan ( ); poKmlPlacemark->set_timeprimitive ( poKmlTimeSpan ); } poKmlTimeSpan->set_begin ( timebuf ); CPLFree( timebuf ); continue; } /***** end *****/ else if ( EQUAL ( name, endfield ) ) { char *timebuf = OGRGetXMLDateTime ( year, month, day, hour, min, sec, tz ); if ( !poKmlTimeSpan ) { poKmlTimeSpan = poKmlFactory->CreateTimeSpan ( ); poKmlPlacemark->set_timeprimitive ( poKmlTimeSpan ); } poKmlTimeSpan->set_end ( timebuf ); CPLFree( timebuf ); continue; } /***** other *****/ poKmlSimpleData = poKmlFactory->CreateSimpleData ( ); poKmlSimpleData->set_name ( name ); poKmlSimpleData->set_text ( poOgrFeat-> GetFieldAsString ( i ) ); break; } case OFTInteger: // Simple 32bit integer /***** extrude *****/ if ( EQUAL ( name, extrudefield ) ) { if ( poKmlPlacemark->has_geometry ( ) && -1 < poOgrFeat->GetFieldAsInteger ( i ) ) { GeometryPtr poKmlGeometry = poKmlPlacemark->get_geometry ( ); ogr2extrude_rec ( poOgrFeat->GetFieldAsInteger ( i ), poKmlGeometry ); } continue; } /***** tessellate *****/ if ( EQUAL ( name, tessellatefield ) ) { if ( poKmlPlacemark->has_geometry ( ) && -1 < poOgrFeat->GetFieldAsInteger ( i ) ) { GeometryPtr poKmlGeometry = poKmlPlacemark->get_geometry ( ); ogr2tessellate_rec ( poOgrFeat->GetFieldAsInteger ( i ), poKmlGeometry ); } continue; } /***** visibility *****/ if ( EQUAL ( name, visibilityfield ) ) { if ( -1 < poOgrFeat->GetFieldAsInteger ( i ) ) poKmlPlacemark->set_visibility ( poOgrFeat-> GetFieldAsInteger ( i ) ); continue; } /***** other *****/ poKmlSimpleData = poKmlFactory->CreateSimpleData ( ); poKmlSimpleData->set_name ( name ); poKmlSimpleData->set_text ( poOgrFeat->GetFieldAsString ( i ) ); break; case OFTReal: // Double Precision floating point { poKmlSimpleData = poKmlFactory->CreateSimpleData ( ); poKmlSimpleData->set_name ( name ); char* pszStr = CPLStrdup( poOgrFeat->GetFieldAsString ( i ) ); /* Use point as decimal separator */ char* pszComma = strchr(pszStr, ','); if (pszComma) *pszComma = '.'; poKmlSimpleData->set_text ( pszStr ); CPLFree(pszStr); break; } case OFTStringList: // Array of strings case OFTIntegerList: // List of 32bit integers case OFTRealList: // List of doubles case OFTBinary: // Raw Binary data case OFTWideStringList: // deprecated default: /***** other *****/ poKmlSimpleData = poKmlFactory->CreateSimpleData ( ); poKmlSimpleData->set_name ( name ); poKmlSimpleData->set_text ( poOgrFeat->GetFieldAsString ( i ) ); break; } poKmlSchemaData->add_simpledata ( poKmlSimpleData ); } /***** dont add it to the placemark unless there is data *****/ if ( poKmlSchemaData->get_simpledata_array_size ( ) > 0 ) { ExtendedDataPtr poKmlExtendedData = poKmlFactory->CreateExtendedData ( ); poKmlExtendedData->add_schemadata ( poKmlSchemaData ); poKmlPlacemark->set_extendeddata ( poKmlExtendedData ); } return; }