示例#1
0
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;
    }
}
示例#2
0
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() );
                    }
                }
            }
        }
    }

}