Opened 3 years ago

Closed 3 years ago

#6845 closed defect (invalid)

retrieve OGRLayerH from GML Layer with 2 geometries

Reported by: mj10777 Owned by: warmerdam
Priority: normal Milestone:
Component: OGR_SF Version:
Severity: major Keywords: GML multiple geometries QGIS
Cc:

Description

For the QGis QgsOgrProvider? class I am attempting to resolve a problem when using a GML file with 2 geometries.

2 problems occur, one of which I can avoid:

1) retrieving the field id based on the geometry field name crashes the application. cause unknown.

  • This number can be retrieved by looping through the result of OGR_FD_GetGeomFieldCount.
int i_field_geometry = OGR_F_GetGeomFieldIndex( fdef_layer, sGeometryName.toUtf8().constData() );

2) Qgis needs to receive a OGRLayer that contains a specific geometry field that is known by name, together with the other non-geometry fields.

For spatialite tables GDALDatasetGetLayerByName can be used by this

  • but from your note, this is not available for most providers
  • and defiantly does not work with the GML sample that you sent me

My assumption is that the layer should be retrieved and somehow deactivate the other geometry fields.

  • OGR_GFld_SetIgnored looked very promising, but Qgis still shows the first geometry field when try to display the second field
  • OGR_GFld_Destroy and OGR_L_DeleteField crashes the application
    • but I believe is intended more for manipulating the original source (which in this case, GML, is also read only).

I could find nothing else in the API documentation that looks promising.


At present, the function looks like this

  • but will always display the first geometry in the layer
    • when the second is being requested
OGRLayerH QgsOgrProviderUtils::OGRGetGeometryNameWrapper( OGRDataSourceH ogrDataSource, QString sLayerName, QString sGeometryName )
{
  OGRLayerH ogrLayer = nullptr;
  QString new_LayerName = sLayerName;
  if ( ( sLayerName.contains( "(" ) ) && ( sLayerName.endsWith( QString( ")" ) ) ) )
  {
    // Extract GeometryName from sent 'table_name(field_name)' from layerName
    QStringList sa_list_name = sLayerName.split( "(" );
    sLayerName = sa_list_name[0];
    sGeometryName = sa_list_name[1].replace( ")", "" );
  }
  else
  {
    new_LayerName =  QString( "%1(%2)" ).arg( sLayerName ).arg( sGeometryName );
  }
  if ( ogrDataSource )
  {
    long layer_count = QgsOgrProviderUtils::OGRGetLayerCountWrapper( ogrDataSource );
    int i_hit = 0;
    for ( long i_layer = 0; i_layer < layer_count; i_layer++ )
    {
      OGRLayerH layer = QgsOgrProviderUtils::OGRGetLayerIndexWrapper( ogrDataSource, i_layer );
      if ( layer )
      {
        OGRFeatureDefnH fdef_layer = OGR_L_GetLayerDefn( layer );
        QString theLayerName = QString::fromUtf8( OGR_FD_GetName( fdef_layer ) );
        if ( sLayerName == QString::fromUtf8( OGR_FD_GetName( fdef_layer ) ) )
        {
          int field_count = OGR_FD_GetGeomFieldCount( fdef_layer ); // count of geometry fields
          // crashes: int i_field_geometry = OGR_F_GetGeomFieldIndex( fdef_layer, sGeometryName.toUtf8().constData() );
          // qDebug() << QString( "-I-> QgsOgrProviderUtils::OGRGetGeometryNameWrapper[%1]: GeometryName[%2] " ).arg( i_field_geometry ).arg( sGeometryName );
          for ( int i_field = 0; i_field < field_count; i_field++ )
          {
            OGRGeomFieldDefnH fdef_geom = OGR_FD_GetGeomFieldDefn( fdef_layer, i_field );
            if ( fdef_geom )
            {
              QString theLayerFieldName = QString::fromUtf8( OGR_GFld_GetNameRef( fdef_geom ) );
              if ( sGeometryName != theLayerFieldName )
              {
                OGR_GFld_SetIgnored( fdef_geom, 1 ); // The first geometry will still be 'activ'
                // crash: OGR_GFld_Destroy( fdef_geom);
                // crash: OGR_L_DeleteField( layer, i_field, theLayerFieldName.toUtf8().constData() );
              }
              else
              {
                i_hit = 1;
              }
            }
          }
          if ( i_hit )
          {
            return layer;
          }
          return ogrLayer;
        }
      }
    }
  }
  return ogrLayer;
}

Change History (1)

comment:1 Changed 3 years ago by Even Rouault

Milestone: 2.2.0
Resolution: invalid
Status: newclosed
Version: svn-trunk

You cannot use OGR_F_GetGeomFieldIndex() with a *feature definition* as the first argument. This should be a *feature* instead. So what you want to use here is OGR_FD_GetGeomFieldIndex

OGR_GFld_SetIgnored() will not modify the feature definition, but just *potentially* avoid values to be retrieved. And indeed calling OGR_GFld_Destroy() or OGR_L_DeleteField() is not what you should do in that case. You must work with the layer and all its geometry fields, but only retrieve the geometry of interest from the feature with OGR_F_GetGeomFieldRef(feature, geom_field_index)

Note: those are not GDAL bugs. So closing that ticket.

Note: See TracTickets for help on using tickets.