bool UAVFlightPlan::exportToKMLFile(const std::string &f, int begin_, int end_) const { bool ret_val = true; if (end_ < 0 || end_ > size()) { end_ = size(); } if (begin_ < 0 || begin_ > size()) { begin_ = 0; } const_iterator it = begin(); // Advance to the first waypoint to save int i = 0; for (; i < begin_; i++, it++); KmlFactory* factory = KmlFactory::GetFactory(); kmldom::DocumentPtr doc = factory->CreateDocument(); for (int j = 1; i < end_ && it != end(); j++,i++, it++) { ostringstream name_; name_ << "Waypoint " << j; // Create a <Point> with <coordinates> from the given Vec3. kmlbase::Vec3 v(it->getLongitude(), it->getLatitude(), it->getAltitude()); kmldom::PointPtr point = kmlconvenience::CreatePointFromVec3(v); PlacemarkPtr place = factory->CreatePlacemark(); place->set_geometry(point); doc->add_feature(place); } // Finally create the kml KmlPtr kml = factory->CreateKml(); kml->set_feature(doc); // Then the file KmlFilePtr kmlfile = KmlFile::CreateFromImport(kml); if (!kmlfile) { cerr << "error: could not create kml file" << endl; return false; } // And write it std::string kml_data; kmlfile->SerializeToString(&kml_data); if (!kmlbase::File::WriteStringToFile(kml_data, f.c_str())) { cerr << "error: write of " << f << " failed" << endl; ret_val = false; } return ret_val; }
OGRErr OGRLIBKMLLayer::DeleteFeature( GIntBig nFIDIn ) { if( !bUpdate || !m_poKmlUpdate ) return OGRERR_UNSUPPORTED_OPERATION; KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory(); DeletePtr poDelete = poKmlFactory->CreateDelete(); m_poKmlUpdate->add_updateoperation(poDelete); PlacemarkPtr poKmlPlacemark = poKmlFactory->CreatePlacemark(); poDelete->add_feature(poKmlPlacemark); const char* pszId = CPLSPrintf("%s." CPL_FRMT_GIB, OGRLIBKMLGetSanitizedNCName(GetName()).c_str(), nFIDIn); poKmlPlacemark->set_targetid(pszId); /***** mark as updated *****/ m_poOgrDS->Updated(); return OGRERR_NONE; }
/** * @brief KmlExport::createTimespanPlacemark Creates a timespan placemark, which allows the * trajectory to be played forward in time. The placemark also contains pertinent data about * the vehicle's state at that timespan * @param timestampPoint * @param lastPlacemarkTime * @param newPlacemarkTime * @return Returns the placemark containing the timespan */ PlacemarkPtr KmlExport::createTimespanPlacemark(const LLAVCoordinates ×tampPoint, quint32 lastPlacemarkTime, quint32 newPlacemarkTime) { // Create coordinates CoordinatesPtr coordinates = factory->CreateCoordinates(); coordinates->add_latlngalt(timestampPoint.latitude, timestampPoint.longitude, timestampPoint.altitude); // Create point, using previous coordinates PointPtr point = factory->CreatePoint(); point->set_extrude(true); // Extrude to ground point->set_altitudemode(kmldom::ALTITUDEMODE_ABSOLUTE); point->set_coordinates(coordinates); // Create the timespan TimeSpanPtr timeSpan = factory->CreateTimeSpan(); QDateTime startTime = QDateTime::currentDateTimeUtc().addMSecs(lastPlacemarkTime); // FIXME: Make it a function of the realtime preferably gotten from the GPS QDateTime endTime = QDateTime::currentDateTimeUtc().addMSecs(newPlacemarkTime); timeSpan->set_begin(startTime.toString(dateTimeFormat).toStdString()); timeSpan->set_end(endTime.toString(dateTimeFormat).toStdString()); // Create an icon style. This arrow icon will be rotated and colored to represent velocity AttitudeActual::DataFields attitudeActualData = attitudeActual->getData(); AirspeedActual::DataFields airspeedActualData = airspeedActual->getData(); IconStylePtr iconStyle = factory->CreateIconStyle(); iconStyle->set_color(mapVelocity2Color(airspeedActualData.CalibratedAirspeed)); iconStyle->set_heading(attitudeActualData.Yaw + 180); //Adding 180 degrees because the arrow art points down, i.e. south. // Create a line style. This defines the style for the "legs" connecting the points to the ground. LineStylePtr lineStyle = factory->CreateLineStyle(); lineStyle->set_color(mapVelocity2Color(timestampPoint.groundspeed)); // Link the style to the icon StylePtr style = factory->CreateStyle(); style->set_linestyle(lineStyle); style->set_iconstyle(iconStyle); // Generate the placemark with all above attributes PlacemarkPtr placemark = factory->CreatePlacemark(); placemark->set_geometry(point); placemark->set_timeprimitive(timeSpan); placemark->set_name(QString("%1").arg(timeStamp / 1000.0).toStdString()); placemark->set_visibility(true); // Set the placemark to use the custom rotated arrow style placemark->set_styleurl("#directiveArrowStyle"); placemark->set_styleselector(style); // Add a nice description to the placemark placemark->set_description(informationString.toStdString()); return placemark; }
void addstylestring2kml ( const char *pszStyleString, StylePtr poKmlStyle, KmlFactory * poKmlFactory, PlacemarkPtr poKmlPlacemark, OGRFeature * poOgrFeat ) { LineStylePtr poKmlLineStyle = NULL; PolyStylePtr poKmlPolyStyle = NULL; IconStylePtr poKmlIconStyle = NULL; LabelStylePtr poKmlLabelStyle = NULL; /***** just bail now if stylestring is empty *****/ if ( !pszStyleString || !*pszStyleString ) { return; } /***** create and init a style mamager with the style string *****/ OGRStyleMgr *poOgrSM = new OGRStyleMgr; poOgrSM->InitStyleString ( pszStyleString ); /***** loop though the style parts *****/ int i; for ( i = 0; i < poOgrSM->GetPartCount ( NULL ); i++ ) { OGRStyleTool *poOgrST = poOgrSM->GetPart ( i, NULL ); if ( !poOgrST ) { continue; } switch ( poOgrST->GetType ( ) ) { case OGRSTCPen: { GBool nullcheck; poKmlLineStyle = poKmlFactory->CreateLineStyle ( ); OGRStylePen *poStylePen = ( OGRStylePen * ) poOgrST; /***** pen color *****/ int nR, nG, nB, nA; const char *pszcolor = poStylePen->Color ( nullcheck ); if ( !nullcheck && poStylePen->GetRGBFromString ( pszcolor, nR, nG, nB, nA ) ) { poKmlLineStyle->set_color ( Color32 ( nA, nB, nG, nR ) ); } double dfWidth = poStylePen->Width ( nullcheck ); if ( nullcheck ) dfWidth = 1.0; poKmlLineStyle->set_width ( dfWidth ); break; } case OGRSTCBrush: { GBool nullcheck; poKmlPolyStyle = poKmlFactory->CreatePolyStyle ( ); OGRStyleBrush *poStyleBrush = ( OGRStyleBrush * ) poOgrST; /***** brush color *****/ int nR, nG, nB, nA; const char *pszcolor = poStyleBrush->ForeColor ( nullcheck ); if ( !nullcheck && poStyleBrush->GetRGBFromString ( pszcolor, nR, nG, nB, nA ) ) { poKmlPolyStyle->set_color ( Color32 ( nA, nB, nG, nR ) ); } break; } case OGRSTCSymbol: { GBool nullcheck; GBool nullcheck2; OGRStyleSymbol *poStyleSymbol = ( OGRStyleSymbol * ) poOgrST; /***** id (kml icon) *****/ const char *pszId = poStyleSymbol->Id ( nullcheck ); if ( !nullcheck ) { if ( !poKmlIconStyle) poKmlIconStyle = poKmlFactory->CreateIconStyle ( ); /***** split it at the ,'s *****/ char **papszTokens = CSLTokenizeString2 ( pszId, ",", CSLT_HONOURSTRINGS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES ); if ( papszTokens ) { /***** for lack of a better solution just take the first one *****/ //todo come up with a better idea if ( papszTokens[0] ) { IconStyleIconPtr poKmlIcon = poKmlFactory->CreateIconStyleIcon ( ); poKmlIcon->set_href ( papszTokens[0] ); poKmlIconStyle->set_icon ( poKmlIcon ); } CSLDestroy ( papszTokens ); } } /***** heading *****/ double heading = poStyleSymbol->Angle ( nullcheck ); if ( !nullcheck ) { if ( !poKmlIconStyle) poKmlIconStyle = poKmlFactory->CreateIconStyle ( ); poKmlIconStyle->set_heading ( heading ); } /***** scale *****/ double dfScale = poStyleSymbol->Size ( nullcheck ); if ( !nullcheck ) { if ( !poKmlIconStyle) poKmlIconStyle = poKmlFactory->CreateIconStyle ( ); poKmlIconStyle->set_scale ( dfScale ); } /***** color *****/ int nR, nG, nB, nA; const char *pszcolor = poStyleSymbol->Color ( nullcheck ); if ( !nullcheck && poOgrST->GetRGBFromString ( pszcolor, nR, nG, nB, nA ) ) { poKmlIconStyle->set_color ( Color32 ( nA, nB, nG, nR ) ); } /***** hotspot *****/ double dfDx = poStyleSymbol->SpacingX ( nullcheck ); double dfDy = poStyleSymbol->SpacingY ( nullcheck2 ); if ( !nullcheck && !nullcheck2 ) { if ( !poKmlIconStyle) poKmlIconStyle = poKmlFactory->CreateIconStyle ( ); HotSpotPtr poKmlHotSpot = poKmlFactory->CreateHotSpot ( ); poKmlHotSpot->set_x ( dfDx ); poKmlHotSpot->set_y ( dfDy ); poKmlIconStyle->set_hotspot ( poKmlHotSpot ); } break; } case OGRSTCLabel: { GBool nullcheck; GBool nullcheck2; poKmlLabelStyle = poKmlFactory->CreateLabelStyle ( ); OGRStyleLabel *poStyleLabel = ( OGRStyleLabel * ) poOgrST; /***** color *****/ int nR, nG, nB, nA; const char *pszcolor = poStyleLabel->ForeColor ( nullcheck ); if ( !nullcheck && poStyleLabel->GetRGBFromString ( pszcolor, nR, nG, nB, nA ) ) { poKmlLabelStyle->set_color ( Color32 ( nA, nB, nG, nR ) ); } /***** scale *****/ double dfScale = poStyleLabel->Stretch ( nullcheck ); if ( !nullcheck ) { dfScale /= 100.0; poKmlLabelStyle->set_scale ( dfScale ); } /***** heading *****/ double heading = poStyleLabel->Angle ( nullcheck ); if ( !nullcheck ) { if ( !poKmlIconStyle) { poKmlIconStyle = poKmlFactory->CreateIconStyle ( ); IconStyleIconPtr poKmlIcon = poKmlFactory->CreateIconStyleIcon ( ); poKmlIconStyle->set_icon ( poKmlIcon ); } poKmlIconStyle->set_heading ( heading ); } /***** hotspot *****/ double dfDx = poStyleLabel->SpacingX ( nullcheck ); double dfDy = poStyleLabel->SpacingY ( nullcheck2 ); if ( !nullcheck && !nullcheck2 ) { if ( !poKmlIconStyle) { poKmlIconStyle = poKmlFactory->CreateIconStyle ( ); IconStyleIconPtr poKmlIcon = poKmlFactory->CreateIconStyleIcon ( ); poKmlIconStyle->set_icon ( poKmlIcon ); } HotSpotPtr poKmlHotSpot = poKmlFactory->CreateHotSpot ( ); poKmlHotSpot->set_x ( dfDx ); poKmlHotSpot->set_y ( dfDy ); poKmlIconStyle->set_hotspot ( poKmlHotSpot ); } /***** label text *****/ const char *pszText = poStyleLabel->TextString ( nullcheck ); if ( !nullcheck ) { if ( poKmlPlacemark ) { poKmlPlacemark->set_name( pszText ); } } break; } case OGRSTCNone: default: break; } delete poOgrST; } if ( poKmlLineStyle ) poKmlStyle->set_linestyle ( poKmlLineStyle ); if ( poKmlPolyStyle ) poKmlStyle->set_polystyle ( poKmlPolyStyle ); if ( poKmlIconStyle ) poKmlStyle->set_iconstyle ( poKmlIconStyle ); if ( poKmlLabelStyle ) poKmlStyle->set_labelstyle ( poKmlLabelStyle ); delete poOgrSM; }
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; } }
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; } } }
/** * @brief KmlExport::CreateLineStringPlacemark Adds a line segment which is colored according to the * vehicle's speed. * @param startPoint Beginning point along line * @param endPoint End point point along line * @return Returns the placemark containing the line segment */ PlacemarkPtr KmlExport::CreateLineStringPlacemark(const LLAVCoordinates &startPoint, const LLAVCoordinates &endPoint, quint32 newPlacemarkTime) { CoordinatesPtr coordinates = factory->CreateCoordinates(); coordinates->add_latlngalt(startPoint.latitude, startPoint.longitude, startPoint.altitude); coordinates->add_latlngalt(endPoint.latitude, endPoint.longitude, endPoint.altitude); LineStringPtr linestring = factory->CreateLineString(); linestring->set_extrude(true); // Extrude to ground linestring->set_altitudemode(kmldom::ALTITUDEMODE_ABSOLUTE); linestring->set_coordinates(coordinates); StyleMapPtr styleMap = factory->CreateStyleMap(); // Add custom balloon style (gets rid of "Directions to here...") // https://groups.google.com/forum/?fromgroups#!topic/kml-support-getting-started/2CqF9oiynRY BalloonStylePtr balloonStyle = factory->CreateBalloonStyle(); balloonStyle->set_text("$[description]"); { double currentVelocity = (startPoint.groundspeed + endPoint.groundspeed)/2; // Set the linestyle. The color is a function of speed. LineStylePtr lineStyle = factory->CreateLineStyle(); lineStyle->set_color(mapVelocity2Color(currentVelocity)); PolyStylePtr polyStyle = factory->CreatePolyStyle(); polyStyle->set_color(mapVelocity2Color(currentVelocity, 100)); // Link the style to the icon StylePtr style = factory->CreateStyle(); style->set_balloonstyle(balloonStyle); style->set_linestyle(lineStyle); style->set_polystyle(polyStyle); PairPtr pair = factory->CreatePair(); pair->set_styleselector(style); pair->set_key(kmldom::STYLESTATE_NORMAL); styleMap->add_pair(pair); } { double currentVelocity = (startPoint.groundspeed + endPoint.groundspeed)/2; // Set the linestyle. The color is a function of speed. LineStylePtr lineStyle = factory->CreateLineStyle(); lineStyle->set_color(mapVelocity2Color(currentVelocity)); PolyStylePtr polyStyle = factory->CreatePolyStyle(); polyStyle->set_color(mapVelocity2Color(currentVelocity, 100)); polyStyle->set_fill(false); // Link the style to the icon StylePtr style = factory->CreateStyle(); style->set_balloonstyle(balloonStyle); style->set_linestyle(lineStyle); style->set_polystyle(polyStyle); PairPtr pair = factory->CreatePair(); pair->set_styleselector(style); pair->set_key(kmldom::STYLESTATE_HIGHLIGHT); styleMap->add_pair(pair); } PlacemarkPtr placemark = factory->CreatePlacemark(); placemark->set_geometry(linestring); placemark->set_styleselector(styleMap); placemark->set_visibility(true); // Create the timespan TimeSpanPtr timeSpan = factory->CreateTimeSpan(); QDateTime startTime = QDateTime::currentDateTimeUtc().addMSecs(newPlacemarkTime); // FIXME: Make this a function of the true time, preferably gotten from the GPS QDateTime endTime = QDateTime::currentDateTimeUtc().addMSecs(newPlacemarkTime); timeSpan->set_begin(startTime.toString(dateTimeFormat).toStdString()); timeSpan->set_end(endTime.toString(dateTimeFormat).toStdString()); // Set the name QDateTime trackTime = QDateTime::currentDateTimeUtc().addMSecs(newPlacemarkTime); // FIXME: Make it a function of the realtime preferably gotten from the GPS placemark->set_name(trackTime.toString(dateTimeFormat).toStdString()); // Add a nice description to the track placemark placemark->set_description(informationString.toStdString()); // Set the timespan placemark->set_timeprimitive(timeSpan); return placemark; }
/** * @brief KmlExport::exportToKML Triggers logfile export to KML. */ bool KmlExport::exportToKML() { bool ret = open(); if (!ret) { qDebug () << "Logfile failed to open during KML export"; return false; } // Parses logfile and generates KML document ret = preparseLogFile(); if (!ret) { qDebug () << "Logfile preparsing failed"; return false; } // Call parser. parseLogFile(); // Add track to <Document> document->add_feature(trackFolder); // Add timespans to <Document> document->add_feature(timestampFolder); // Add ground track to <Document> { LineStringPtr linestring = factory->CreateLineString(); linestring->set_extrude(false); // Do not extrude to ground linestring->set_altitudemode(kmldom::ALTITUDEMODE_CLAMPTOGROUND); linestring->set_coordinates(wallAxes[0]); MultiGeometryPtr multiGeometry = factory->CreateMultiGeometry(); multiGeometry->add_geometry(linestring); PlacemarkPtr placemark = factory->CreatePlacemark(); placemark->set_geometry(multiGeometry); placemark->set_styleurl("#ts_2_tb"); placemark->set_name("Ground track"); document->add_feature(placemark); } // Add wall axes to <Document> FolderPtr folder = factory->CreateFolder(); for (int i=0; i<numberOfWallAxes; i++) { LineStringPtr linestring = factory->CreateLineString(); linestring->set_extrude(false); // Do not extrude to ground linestring->set_altitudemode(kmldom::ALTITUDEMODE_ABSOLUTE); linestring->set_coordinates(wallAxes[i]); MultiGeometryPtr multiGeometry = factory->CreateMultiGeometry(); multiGeometry->add_geometry(linestring); PlacemarkPtr placemark = factory->CreatePlacemark(); placemark->set_geometry(multiGeometry); placemark->set_styleurl("#ts_1_tb"); folder->add_feature(placemark); folder->set_name("Wall axes"); } document->add_feature(folder); // Create <kml> and give it <Document>. KmlPtr kml = factory->CreateKml(); kml->set_feature(document); // kml takes ownership. // Serialize to XML std::string kml_data = kmldom::SerializePretty(kml); // Save to file if (QFileInfo(outputFileName).suffix().toLower() == "kmz") { if (!kmlengine::KmzFile::WriteKmz(outputFileName.toStdString().c_str(), kml_data)) { qDebug() << "KMZ write failed: " << outputFileName; QMessageBox::critical(new QWidget(),"KMZ write failed", "Failed to write KMZ file."); return false; } } else if (QFileInfo(outputFileName).suffix().toLower() == "kml") { if (!kmlbase::File::WriteStringToFile(kml_data, outputFileName.toStdString())) { qDebug() << "KML write failed: " << outputFileName; QMessageBox::critical(new QWidget(),"KML write failed", "Failed to write KML file."); return false; } } else { qDebug() << "Write failed. Invalid file name:" << outputFileName; QMessageBox::critical(new QWidget(),"Write failed", "Failed to write file. Invalid filename"); return false; } return 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() ); } } } } } }
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; }