Example #1
0
OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
{
    if( poFeatureDefn != NULL )
        return poFeatureDefn;

    poFeatureDefn = new OGRFeatureDefn( osName );
    poFeatureDefn->Reference();
    poFeatureDefn->SetGeomType(wkbNone);

    int iCompareFirstIndex = 0;
    if( osSourceLayerFieldName.size() )
    {
        OGRFieldDefn oField(osSourceLayerFieldName, OFTString);
        poFeatureDefn->AddFieldDefn(&oField);
        iCompareFirstIndex = 1;
    }

    if( eFieldStrategy == FIELD_SPECIFIED )
    {
        int i;
        for(i = 0; i < nFields; i++)
            poFeatureDefn->AddFieldDefn(papoFields[i]);
        for(i = 0; i < nGeomFields; i++)
        {
            poFeatureDefn->AddGeomFieldDefn(new OGRUnionLayerGeomFieldDefn(papoGeomFields[i]), FALSE);
            OGRUnionLayerGeomFieldDefn* poGeomFieldDefn =
                (OGRUnionLayerGeomFieldDefn* ) poFeatureDefn->GetGeomFieldDefn(i);

            if( poGeomFieldDefn->bGeomTypeSet == FALSE ||
                poGeomFieldDefn->bSRSSet == FALSE )
            {
                for(int iLayer = 0; iLayer < nSrcLayers; iLayer++)
                {
                    OGRFeatureDefn* poSrcFeatureDefn =
                                papoSrcLayers[iLayer]->GetLayerDefn();
                    int nIndex =
                        poSrcFeatureDefn->GetGeomFieldIndex(poGeomFieldDefn->GetNameRef());
                    if( nIndex >= 0 )
                    {
                        OGRGeomFieldDefn* poSrcGeomFieldDefn =
                            poSrcFeatureDefn->GetGeomFieldDefn(nIndex);
                        if( poGeomFieldDefn->bGeomTypeSet == FALSE )
                        {
                            poGeomFieldDefn->bGeomTypeSet = TRUE;
                            poGeomFieldDefn->SetType(poSrcGeomFieldDefn->GetType());
                        }
                        if( poGeomFieldDefn->bSRSSet == FALSE )
                        {
                            poGeomFieldDefn->bSRSSet = TRUE;
                            poGeomFieldDefn->SetSpatialRef(poSrcGeomFieldDefn->GetSpatialRef());
                            if( i == 0 && poGlobalSRS == NULL )
                            {
                                poGlobalSRS = poSrcGeomFieldDefn->GetSpatialRef();
                                if( poGlobalSRS != NULL )
                                    poGlobalSRS->Reference();
                            }
                        }
                        break;
                    }
                }
            }
        }
    }
    else if( eFieldStrategy == FIELD_FROM_FIRST_LAYER )
    {
        OGRFeatureDefn* poSrcFeatureDefn = papoSrcLayers[0]->GetLayerDefn();
        int i;
        for(i = 0; i < poSrcFeatureDefn->GetFieldCount(); i++)
            poFeatureDefn->AddFieldDefn(poSrcFeatureDefn->GetFieldDefn(i));
        for(i = 0;  nGeomFields != - 1 && i < poSrcFeatureDefn->GetGeomFieldCount(); i++)
        {
            OGRGeomFieldDefn* poFldDefn = poSrcFeatureDefn->GetGeomFieldDefn(i);
            poFeatureDefn->AddGeomFieldDefn(
                new OGRUnionLayerGeomFieldDefn(poFldDefn), FALSE);
        }
    }
    else if (eFieldStrategy == FIELD_UNION_ALL_LAYERS )
    {
        if( nGeomFields == 1 )
        {
            poFeatureDefn->AddGeomFieldDefn(
                        new OGRUnionLayerGeomFieldDefn(papoGeomFields[0]), FALSE);
        }

        for(int iLayer = 0; iLayer < nSrcLayers; iLayer++)
        {
            OGRFeatureDefn* poSrcFeatureDefn =
                                papoSrcLayers[iLayer]->GetLayerDefn();

            /* Add any field that is found in the source layers */
            int i;
            for(i = 0; i < poSrcFeatureDefn->GetFieldCount(); i++)
            {
                OGRFieldDefn* poSrcFieldDefn = poSrcFeatureDefn->GetFieldDefn(i);
                int nIndex =
                    poFeatureDefn->GetFieldIndex(poSrcFieldDefn->GetNameRef());
                if( nIndex < 0 )
                    poFeatureDefn->AddFieldDefn(poSrcFieldDefn);
                else
                {
                    OGRFieldDefn* poFieldDefn =
                                        poFeatureDefn->GetFieldDefn(nIndex);
                    MergeFieldDefn(poFieldDefn, poSrcFieldDefn);
                }
            }

            for(i = 0; nGeomFields != - 1 && i < poSrcFeatureDefn->GetGeomFieldCount(); i++)
            {
                OGRGeomFieldDefn* poSrcFieldDefn = poSrcFeatureDefn->GetGeomFieldDefn(i);
                int nIndex =
                    poFeatureDefn->GetGeomFieldIndex(poSrcFieldDefn->GetNameRef());
                if( nIndex < 0 )
                {
                    poFeatureDefn->AddGeomFieldDefn(
                        new OGRUnionLayerGeomFieldDefn(poSrcFieldDefn), FALSE);
                    if( poFeatureDefn->GetGeomFieldCount() == 1 && nGeomFields == 0 &&
                        GetSpatialRef() != NULL )
                    {
                        OGRUnionLayerGeomFieldDefn* poGeomFieldDefn =
                            (OGRUnionLayerGeomFieldDefn* ) poFeatureDefn->GetGeomFieldDefn(0);
                        poGeomFieldDefn->bSRSSet = TRUE;
                        poGeomFieldDefn->SetSpatialRef(GetSpatialRef());
                    }
                }
                else
                {
                    if( nIndex == 0 && nGeomFields == 1 )
                    {
                        OGRUnionLayerGeomFieldDefn* poGeomFieldDefn =
                            (OGRUnionLayerGeomFieldDefn* ) poFeatureDefn->GetGeomFieldDefn(0);
                        if( poGeomFieldDefn->bGeomTypeSet == FALSE )
                        {
                            poGeomFieldDefn->bGeomTypeSet = TRUE;
                            poGeomFieldDefn->SetType(poSrcFieldDefn->GetType());
                        }
                        if( poGeomFieldDefn->bSRSSet == FALSE )
                        {
                            poGeomFieldDefn->bSRSSet = TRUE;
                            poGeomFieldDefn->SetSpatialRef(poSrcFieldDefn->GetSpatialRef());
                        }
                    }
                    /* TODO: merge type, SRS, extent ? */
                }
            }
        }
    }
    else if (eFieldStrategy == FIELD_INTERSECTION_ALL_LAYERS )
    {
        OGRFeatureDefn* poSrcFeatureDefn = papoSrcLayers[0]->GetLayerDefn();
        int i;
        for(i = 0; i < poSrcFeatureDefn->GetFieldCount(); i++)
            poFeatureDefn->AddFieldDefn(poSrcFeatureDefn->GetFieldDefn(i));
        for(i = 0; i < poSrcFeatureDefn->GetGeomFieldCount(); i++)
        {
            OGRGeomFieldDefn* poFldDefn = poSrcFeatureDefn->GetGeomFieldDefn(i);
            poFeatureDefn->AddGeomFieldDefn(
                new OGRUnionLayerGeomFieldDefn(poFldDefn), FALSE);
        }

        /* Remove any field that is not found in the source layers */
        for(int iLayer = 1; iLayer < nSrcLayers; iLayer++)
        {
            OGRFeatureDefn* l_poSrcFeatureDefn =
                                        papoSrcLayers[iLayer]->GetLayerDefn();
            for(i = iCompareFirstIndex; i < poFeatureDefn->GetFieldCount();)
            {
                OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(i);
                int nSrcIndex = l_poSrcFeatureDefn->GetFieldIndex(
                                                    poFieldDefn->GetNameRef());
                if( nSrcIndex < 0 )
                {
                    poFeatureDefn->DeleteFieldDefn(i);
                }
                else
                {
                    OGRFieldDefn* poSrcFieldDefn =
                        l_poSrcFeatureDefn->GetFieldDefn(nSrcIndex);
                    MergeFieldDefn(poFieldDefn, poSrcFieldDefn);

                    i ++;
                }
            }
            for(i = 0; i < poFeatureDefn->GetGeomFieldCount();)
            {
                OGRGeomFieldDefn* poFieldDefn = poFeatureDefn->GetGeomFieldDefn(i);
                int nSrcIndex = l_poSrcFeatureDefn->GetGeomFieldIndex(
                                                    poFieldDefn->GetNameRef());
                if( nSrcIndex < 0 )
                {
                    poFeatureDefn->DeleteGeomFieldDefn(i);
                }
                else
                {
                    /* TODO: merge type, SRS, extent ? */

                    i ++;
                }
            }
        }
    }

    return poFeatureDefn;
}
Example #2
0
OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
                                        CPLXMLNode *psLTree,
                                        const char *pszVRTDirectory,
                                        int bUpdate,
                                        int nRecLevel)
{
    CPLXMLNode *psSubNode;

    if( !EQUAL(psLTree->pszValue,"OGRVRTUnionLayer") )
        return NULL;

/* -------------------------------------------------------------------- */
/*      Get layer name.                                                 */
/* -------------------------------------------------------------------- */
    const char *pszLayerName = CPLGetXMLValue( psLTree, "name", NULL );

    if( pszLayerName == NULL )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "Missing name attribute on OGRVRTUnionLayer" );
        return FALSE;
    }

/* -------------------------------------------------------------------- */
/*      Do we have a fixed geometry type?  If not derive from the       */
/*      source layer.                                                   */
/* -------------------------------------------------------------------- */
    const char* pszGType = CPLGetXMLValue( psLTree, "GeometryType", NULL );
    int bGlobalGeomTypeSet = FALSE;
    OGRwkbGeometryType eGlobalGeomType = wkbUnknown;
    if( pszGType != NULL )
    {
        int bError;
        bGlobalGeomTypeSet = TRUE;
        eGlobalGeomType = OGRVRTGetGeometryType(pszGType, &bError);
        if( bError )
        {
            CPLError( CE_Failure, CPLE_AppDefined,
                    "GeometryType %s not recognised.",
                    pszGType );
            return NULL;
        }
    }

/* -------------------------------------------------------------------- */
/*      Apply a spatial reference system if provided                    */
/* -------------------------------------------------------------------- */
     const char* pszLayerSRS = CPLGetXMLValue( psLTree, "LayerSRS", NULL );
     OGRSpatialReference* poGlobalSRS = NULL;
     int bGlobalSRSSet = FALSE;
     if( pszLayerSRS != NULL )
     {
         bGlobalSRSSet = TRUE;
         if( !EQUAL(pszLayerSRS,"NULL") )
         {
             OGRSpatialReference oSRS;

             if( oSRS.SetFromUserInput( pszLayerSRS ) != OGRERR_NONE )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Failed to import LayerSRS `%s'.", pszLayerSRS );
                 return FALSE;
             }
             poGlobalSRS = oSRS.Clone();
         }
     }

/* -------------------------------------------------------------------- */
/*      Find field declarations.                                        */
/* -------------------------------------------------------------------- */
    OGRFieldDefn** papoFields = NULL;
    int nFields = 0;
    OGRUnionLayerGeomFieldDefn** papoGeomFields = NULL;
    int nGeomFields = 0;

    for( psSubNode=psLTree->psChild;
         psSubNode != NULL;
         psSubNode=psSubNode->psNext )
    {
         if( psSubNode->eType != CXT_Element )
             continue;

         if( psSubNode->eType == CXT_Element && EQUAL(psSubNode->pszValue,"Field") )
         {
/* -------------------------------------------------------------------- */
/*      Field name.                                                     */
/* -------------------------------------------------------------------- */
             const char *pszName = CPLGetXMLValue( psSubNode, "name", NULL );
             if( pszName == NULL )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Unable to identify Field name." );
                 break;
             }

             OGRFieldDefn oFieldDefn( pszName, OFTString );

/* -------------------------------------------------------------------- */
/*      Type                                                            */
/* -------------------------------------------------------------------- */
             const char *pszArg = CPLGetXMLValue( psSubNode, "type", NULL );

             if( pszArg != NULL )
             {
                 int iType;

                 for( iType = 0; iType <= (int) OFTMaxType; iType++ )
                 {
                     if( EQUAL(pszArg,OGRFieldDefn::GetFieldTypeName(
                                   (OGRFieldType)iType)) )
                     {
                         oFieldDefn.SetType( (OGRFieldType) iType );
                         break;
                     }
                 }

                 if( iType > (int) OFTMaxType )
                 {
                     CPLError( CE_Failure, CPLE_AppDefined,
                               "Unable to identify Field type '%s'.",
                               pszArg );
                     break;
                 }
             }

/* -------------------------------------------------------------------- */
/*      Width and precision.                                            */
/* -------------------------------------------------------------------- */
             int nWidth = atoi(CPLGetXMLValue( psSubNode, "width", "0" ));
             if (nWidth < 0)
             {
                CPLError( CE_Failure, CPLE_IllegalArg,
                          "Invalid width for field %s.",
                          pszName );
                break;
             }
             oFieldDefn.SetWidth(nWidth);

             int nPrecision = atoi(CPLGetXMLValue( psSubNode, "precision", "0" ));
             if (nPrecision < 0 || nPrecision > 1024)
             {
                CPLError( CE_Failure, CPLE_IllegalArg,
                          "Invalid precision for field %s.",
                          pszName );
                break;
             }
             oFieldDefn.SetPrecision(nPrecision);

             papoFields = (OGRFieldDefn**) CPLRealloc(papoFields,
                                        sizeof(OGRFieldDefn*) * (nFields + 1));
             papoFields[nFields] = new OGRFieldDefn(&oFieldDefn);
             nFields ++;
         }

         else if( psSubNode->eType == CXT_Element &&
                  EQUAL(psSubNode->pszValue,"GeometryField") )
         {
             const char *pszName = CPLGetXMLValue( psSubNode, "name", NULL );
             if( pszName == NULL )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Unable to identify GeometryField name." );
                 break;
             }

             pszGType = CPLGetXMLValue( psSubNode, "GeometryType", NULL );
             if( pszGType == NULL && nGeomFields == 0 )
                 pszGType = CPLGetXMLValue( psLTree, "GeometryType", NULL );
             OGRwkbGeometryType eGeomType = wkbUnknown;
             int bGeomTypeSet = FALSE;
             if( pszGType != NULL )
             {
                int bError;
                eGeomType = OGRVRTGetGeometryType(pszGType, &bError);
                bGeomTypeSet = TRUE;
                if( bError || eGeomType == wkbNone )
                {
                    CPLError( CE_Failure, CPLE_AppDefined,
                            "GeometryType %s not recognised.",
                            pszGType );
                    break;
                }
             }

             const char* pszSRS = CPLGetXMLValue( psSubNode, "SRS", NULL );
             if( pszSRS == NULL && nGeomFields == 0 )
                 pszSRS = CPLGetXMLValue( psLTree, "LayerSRS", NULL );
             OGRSpatialReference* poSRS = NULL;
             int bSRSSet = FALSE;
             if( pszSRS != NULL )
             {
                 bSRSSet = TRUE;
                 if( !EQUAL(pszSRS,"NULL") )
                 {
                    OGRSpatialReference oSRS;

                    if( oSRS.SetFromUserInput( pszSRS ) != OGRERR_NONE )
                    {
                        CPLError( CE_Failure, CPLE_AppDefined,
                                "Failed to import SRS `%s'.", pszSRS );
                        break;
                    }
                    poSRS = oSRS.Clone();
                }
             }

             OGRUnionLayerGeomFieldDefn* poFieldDefn =
                    new OGRUnionLayerGeomFieldDefn(pszName, eGeomType);
             if( poSRS != NULL )
             {
                poFieldDefn->SetSpatialRef(poSRS);
                poSRS->Dereference();
             }
             poFieldDefn->bGeomTypeSet = bGeomTypeSet;
             poFieldDefn->bSRSSet = bSRSSet;

             const char* pszExtentXMin = CPLGetXMLValue( psSubNode, "ExtentXMin", NULL );
             const char* pszExtentYMin = CPLGetXMLValue( psSubNode, "ExtentYMin", NULL );
             const char* pszExtentXMax = CPLGetXMLValue( psSubNode, "ExtentXMax", NULL );
             const char* pszExtentYMax = CPLGetXMLValue( psSubNode, "ExtentYMax", NULL );
             if( pszExtentXMin != NULL && pszExtentYMin != NULL &&
                 pszExtentXMax != NULL && pszExtentYMax != NULL )
             {
                poFieldDefn->sStaticEnvelope.MinX = CPLAtof(pszExtentXMin);
                poFieldDefn->sStaticEnvelope.MinY = CPLAtof(pszExtentYMin);
                poFieldDefn->sStaticEnvelope.MaxX = CPLAtof(pszExtentXMax);
                poFieldDefn->sStaticEnvelope.MaxY = CPLAtof(pszExtentYMax);
             }

             papoGeomFields = (OGRUnionLayerGeomFieldDefn**) CPLRealloc(papoGeomFields,
                                        sizeof(OGRUnionLayerGeomFieldDefn*) * (nGeomFields + 1));
             papoGeomFields[nGeomFields] = poFieldDefn;
             nGeomFields ++;
         }
    }

/* -------------------------------------------------------------------- */
/*      Set Extent if provided                                          */
/* -------------------------------------------------------------------- */
    const char* pszExtentXMin = CPLGetXMLValue( psLTree, "ExtentXMin", NULL );
    const char* pszExtentYMin = CPLGetXMLValue( psLTree, "ExtentYMin", NULL );
    const char* pszExtentXMax = CPLGetXMLValue( psLTree, "ExtentXMax", NULL );
    const char* pszExtentYMax = CPLGetXMLValue( psLTree, "ExtentYMax", NULL );

    if( eGlobalGeomType != wkbNone && nGeomFields == 0 &&
        (bGlobalGeomTypeSet || bGlobalSRSSet ||
         (pszExtentXMin != NULL && pszExtentYMin != NULL &&
          pszExtentXMax != NULL && pszExtentYMax != NULL)) )
    {
        OGRUnionLayerGeomFieldDefn* poFieldDefn =
                new OGRUnionLayerGeomFieldDefn("", eGlobalGeomType);
        if( poGlobalSRS != NULL )
        {
            poFieldDefn->SetSpatialRef(poGlobalSRS);
            poGlobalSRS->Dereference();
            poGlobalSRS = NULL;
        }
        poFieldDefn->bGeomTypeSet = bGlobalGeomTypeSet;
        poFieldDefn->bSRSSet = bGlobalSRSSet;
        if( pszExtentXMin != NULL && pszExtentYMin != NULL &&
            pszExtentXMax != NULL && pszExtentYMax != NULL )
        {
            poFieldDefn->sStaticEnvelope.MinX = CPLAtof(pszExtentXMin);
            poFieldDefn->sStaticEnvelope.MinY = CPLAtof(pszExtentYMin);
            poFieldDefn->sStaticEnvelope.MaxX = CPLAtof(pszExtentXMax);
            poFieldDefn->sStaticEnvelope.MaxY = CPLAtof(pszExtentYMax);
        }

        papoGeomFields = (OGRUnionLayerGeomFieldDefn**) CPLRealloc(papoGeomFields,
                                sizeof(OGRUnionLayerGeomFieldDefn*) * (nGeomFields + 1));
        papoGeomFields[nGeomFields] = poFieldDefn;
        nGeomFields ++;
    }
    else
    {
        delete poGlobalSRS;
        poGlobalSRS = NULL;
    }

/* -------------------------------------------------------------------- */
/*      Find source layers                                              */
/* -------------------------------------------------------------------- */

    int nSrcLayers = 0;
    OGRLayer** papoSrcLayers = NULL;

    for( psSubNode=psLTree->psChild;
         psSubNode != NULL;
         psSubNode=psSubNode->psNext )
    {
        if( psSubNode->eType != CXT_Element )
            continue;

        OGRLayer* poSrcLayer = InstanciateLayer(psSubNode, pszVRTDirectory,
                                           bUpdate, nRecLevel + 1);
        if( poSrcLayer != NULL )
        {
            papoSrcLayers = (OGRLayer**)
                CPLRealloc(papoSrcLayers, sizeof(OGRLayer*) * (nSrcLayers + 1));
            papoSrcLayers[nSrcLayers] = poSrcLayer;
            nSrcLayers ++;
        }
    }

    if( nSrcLayers == 0 )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "Cannot find source layers" );
        int iField;
        for(iField = 0; iField < nFields; iField++)
            delete papoFields[iField];
        CPLFree(papoFields);
        for(iField = 0; iField < nGeomFields; iField++)
            delete papoGeomFields[iField];
        CPLFree(papoGeomFields);
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Build the OGRUnionLayer.                                        */
/* -------------------------------------------------------------------- */
    OGRUnionLayer* poLayer = new OGRUnionLayer( pszLayerName,
                                                nSrcLayers,
                                                papoSrcLayers,
                                                TRUE );

/* -------------------------------------------------------------------- */
/*      Set the source layer field name attribute.                      */
/* -------------------------------------------------------------------- */
    const char* pszSourceLayerFieldName =
        CPLGetXMLValue( psLTree, "SourceLayerFieldName", NULL );
    poLayer->SetSourceLayerFieldName(pszSourceLayerFieldName);

/* -------------------------------------------------------------------- */
/*      Set the PreserveSrcFID attribute.                               */
/* -------------------------------------------------------------------- */
    int bPreserveSrcFID = FALSE;
    const char* pszPreserveFID = CPLGetXMLValue( psLTree, "PreserveSrcFID", NULL );
    if( pszPreserveFID != NULL )
        bPreserveSrcFID = CSLTestBoolean(pszPreserveFID);
    poLayer->SetPreserveSrcFID(bPreserveSrcFID);

/* -------------------------------------------------------------------- */
/*      Set fields                                                      */
/* -------------------------------------------------------------------- */
    FieldUnionStrategy eFieldStrategy = FIELD_UNION_ALL_LAYERS;
    const char* pszFieldStrategy = CPLGetXMLValue( psLTree, "FieldStrategy", NULL );
    if( pszFieldStrategy != NULL )
    {
        if( EQUAL(pszFieldStrategy, "FirstLayer") )
            eFieldStrategy = FIELD_FROM_FIRST_LAYER;
        else if( EQUAL(pszFieldStrategy, "Union") )
            eFieldStrategy = FIELD_UNION_ALL_LAYERS;
        else if( EQUAL(pszFieldStrategy, "Intersection") )
            eFieldStrategy = FIELD_INTERSECTION_ALL_LAYERS;
        else
        {
            CPLError( CE_Warning, CPLE_AppDefined,
                      "Unhandled value for FieldStrategy `%s'.", pszFieldStrategy );
        }
    }
    if( nFields != 0 || nGeomFields > 1 )
    {
        if( pszFieldStrategy != NULL )
            CPLError( CE_Warning, CPLE_AppDefined,
                      "Ignoring FieldStrategy value, because explicit Field or GeometryField is provided") ;
        eFieldStrategy = FIELD_SPECIFIED;
    }

    poLayer->SetFields(eFieldStrategy, nFields, papoFields,
                       (nGeomFields == 0 && eGlobalGeomType == wkbNone) ? -1 : nGeomFields,
                       papoGeomFields);
    int iField;
    for(iField = 0; iField < nFields; iField++)
        delete papoFields[iField];
    CPLFree(papoFields);
    for(iField = 0; iField < nGeomFields; iField++)
        delete papoGeomFields[iField];
    CPLFree(papoGeomFields);

/* -------------------------------------------------------------------- */
/*      Set FeatureCount if provided                                    */
/* -------------------------------------------------------------------- */
    const char* pszFeatureCount = CPLGetXMLValue( psLTree, "FeatureCount", NULL );
    if( pszFeatureCount != NULL )
    {
        poLayer->SetFeatureCount(atoi(pszFeatureCount));
    }

    return poLayer;
}