コード例 #1
0
bool QgsCachedFeatureIterator::fetchFeature( QgsFeature &f )
{
  f.setValid( false );

  if ( mClosed )
    return false;

  while ( mFeatureIdIterator != mFeatureIds.constEnd() )
  {
    if ( !mVectorLayerCache->mCache.contains( *mFeatureIdIterator ) )
    {
      ++mFeatureIdIterator;
      continue;
    }

    f = QgsFeature( *mVectorLayerCache->mCache[*mFeatureIdIterator]->feature() );
    ++mFeatureIdIterator;
    if ( mRequest.acceptFeature( f ) )
    {
      f.setValid( true );
      geometryToDestinationCrs( f, mTransform );
      return true;
    }
  }
  close();
  return false;
}
コード例 #2
0
bool QgsOgrFeatureIterator::fetchFeatureWithId( QgsFeatureId id, QgsFeature &feature ) const
{
  feature.setValid( false );
  gdal::ogr_feature_unique_ptr fet;

#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,2,0)
  if ( !QgsOgrProviderUtils::canDriverShareSameDatasetAmongLayers( mSource->mDriverName ) )
  {
    OGRLayerH nextFeatureBelongingLayer;
    bool found = false;
    // First pass: try to read from the last feature, in the hope the dataset
    // returns them in increasing feature id number (and as we use a std::set
    // for mFilterFids, we get them in increasing number by the iterator)
    // Second pass: reset before reading
    for ( int passNumber = 0; passNumber < 2; passNumber++ )
    {
      while ( fet.reset( GDALDatasetGetNextFeature(
                           mConn->ds, &nextFeatureBelongingLayer, nullptr, nullptr, nullptr ) ), fet )
      {
        if ( nextFeatureBelongingLayer == mOgrLayer )
        {
          if ( OGR_F_GetFID( fet.get() ) == FID_TO_NUMBER( id ) )
          {
            found = true;
            break;
          }
        }
      }
      if ( found || passNumber == 1 )
      {
        break;
      }
      GDALDatasetResetReading( mConn->ds );
    }

    if ( !found )
    {
      return false;
    }
  }
  else
#endif
  {
    fet.reset( OGR_L_GetFeature( mOgrLayer, FID_TO_NUMBER( id ) ) );
  }

  if ( !fet )
  {
    return false;
  }

  if ( !readFeature( std::move( fet ), feature ) )
    return false;

  feature.setValid( true );
  geometryToDestinationCrs( feature, mTransform );
  return true;
}
コード例 #3
0
bool QgsMemoryFeatureIterator::nextFeatureTraverseAll( QgsFeature &feature )
{
  bool hasFeature = false;

  // option 2: traversing the whole layer
  while ( mSelectIterator != mSource->mFeatures.constEnd() )
  {
    if ( mFilterRect.isNull() )
    {
      // selection rect empty => using all features
      hasFeature = true;
    }
    else
    {
      if ( mRequest.flags() & QgsFeatureRequest::ExactIntersect )
      {
        // using exact test when checking for intersection
        if ( mSelectIterator->hasGeometry() && mSelectRectEngine->intersects( mSelectIterator->geometry().constGet() ) )
          hasFeature = true;
      }
      else
      {
        // check just bounding box against rect when not using intersection
        if ( mSelectIterator->hasGeometry() && mSelectIterator->geometry().boundingBox().intersects( mFilterRect ) )
          hasFeature = true;
      }
    }

    if ( mSubsetExpression )
    {
      mSource->mExpressionContext.setFeature( *mSelectIterator );
      if ( !mSubsetExpression->evaluate( &mSource->mExpressionContext ).toBool() )
        hasFeature = false;
    }

    if ( hasFeature )
      break;

    ++mSelectIterator;
  }

  // copy feature
  if ( hasFeature )
  {
    feature = mSelectIterator.value();
    ++mSelectIterator;
    feature.setValid( true );
    feature.setFields( mSource->mFields ); // allow name-based attribute lookups
    geometryToDestinationCrs( feature, mTransform );
  }
  else
    close();

  return hasFeature;
}
コード例 #4
0
bool QgsOgrFeatureIterator::checkFeature( gdal::ogr_feature_unique_ptr &fet, QgsFeature &feature )
{
  if ( !readFeature( std::move( fet ), feature ) )
    return false;

  if ( !mFilterRect.isNull() && ( !feature.hasGeometry() || feature.geometry().isEmpty() ) )
    return false;

  // we have a feature, end this cycle
  feature.setValid( true );
  geometryToDestinationCrs( feature, mTransform );
  return true;
}
コード例 #5
0
bool QgsMemoryFeatureIterator::nextFeatureUsingList( QgsFeature &feature )
{
  bool hasFeature = false;

  // option 1: we have a list of features to traverse
  while ( mFeatureIdListIterator != mFeatureIdList.constEnd() )
  {
    if ( !mFilterRect.isNull() && mRequest.flags() & QgsFeatureRequest::ExactIntersect )
    {
      // do exact check in case we're doing intersection
      if ( mSource->mFeatures.value( *mFeatureIdListIterator ).hasGeometry() && mSelectRectEngine->intersects( mSource->mFeatures.value( *mFeatureIdListIterator ).geometry().constGet() ) )
        hasFeature = true;
    }
    else
      hasFeature = true;

    if ( mSubsetExpression )
    {
      mSource->mExpressionContext.setFeature( mSource->mFeatures.value( *mFeatureIdListIterator ) );
      if ( !mSubsetExpression->evaluate( &mSource->mExpressionContext ).toBool() )
        hasFeature = false;
    }

    if ( hasFeature )
      break;

    ++mFeatureIdListIterator;
  }

  // copy feature
  if ( hasFeature )
  {
    feature = mSource->mFeatures.value( *mFeatureIdListIterator );
    ++mFeatureIdListIterator;
  }
  else
    close();

  if ( hasFeature )
  {
    feature.setFields( mSource->mFields ); // allow name-based attribute lookups
    geometryToDestinationCrs( feature, mTransform );
  }

  return hasFeature;
}
コード例 #6
0
bool QgsCachedFeatureWriterIterator::fetchFeature( QgsFeature &f )
{
  if ( mClosed )
  {
    f.setValid( false );
    return false;
  }
  if ( mFeatIt.nextFeature( f ) )
  {
    // As long as features can be fetched from the provider: Write them to cache
    mVectorLayerCache->cacheFeature( f );
    mFids.insert( f.id() );
    geometryToDestinationCrs( f, mTransform );
    return true;
  }
  else
  {
    // Once no more features can be fetched: Inform the cache, that
    // the request has been completed
    mVectorLayerCache->requestCompleted( mRequest, mFids );
    return false;
  }
}
コード例 #7
0
bool QgsVirtualLayerFeatureIterator::fetchFeature( QgsFeature &feature )
{
  feature.setValid( false );

  if ( mClosed )
  {
    return false;
  }


  bool skipFeature = false;
  do
  {
    if ( mQuery->step() != SQLITE_ROW )
    {
      return false;
    }

    feature.setFields( mSource->mFields, /* init */ true );

    if ( mSource->mDefinition.uid().isNull() &&
         mRequest.filterType() != QgsFeatureRequest::FilterFid )
    {
      // no id column => autoincrement
      feature.setId( mFid++ );
    }
    else
    {
      // first column: uid
      feature.setId( mQuery->columnInt64( 0 ) );
    }

    int n = mQuery->columnCount();
    int i = 0;
    const auto constMAttributes = mAttributes;
    for ( int idx : constMAttributes )
    {
      int type = mQuery->columnType( i + 1 );
      switch ( type )
      {
        case SQLITE_INTEGER:
          feature.setAttribute( idx, mQuery->columnInt64( i + 1 ) );
          break;
        case SQLITE_FLOAT:
          feature.setAttribute( idx, mQuery->columnDouble( i + 1 ) );
          break;
        case SQLITE_TEXT:
        default:
          feature.setAttribute( idx, mQuery->columnText( i + 1 ) );
          break;
      };
      i++;
    }
    if ( n > mAttributes.size() + 1 )
    {
      // geometry field
      QByteArray blob( mQuery->columnBlob( n - 1 ) );
      if ( blob.size() > 0 )
      {
        feature.setGeometry( spatialiteBlobToQgsGeometry( blob.constData(), blob.size() ) );
      }
      else
      {
        feature.clearGeometry();
      }
    }

    feature.setValid( true );
    geometryToDestinationCrs( feature, mTransform );

    // if the FilterRect has not been applied on the query
    // apply it here by skipping features until they intersect
    if ( mSource->mDefinition.uid().isNull() && feature.hasGeometry() && mSource->mDefinition.hasDefinedGeometry() && !mFilterRect.isNull() )
    {
      if ( mRequest.flags() & QgsFeatureRequest::ExactIntersect )
      {
        // using exact test when checking for intersection
        skipFeature = !mRectEngine->intersects( feature.geometry().constGet() );
      }
      else
      {
        // check just bounding box against rect when not using intersection
        skipFeature = !feature.geometry().boundingBox().intersects( mFilterRect );
      }
    }
  }
  while ( skipFeature );

  return true;
}
コード例 #8
0
ファイル: qgsgpxfeatureiterator.cpp プロジェクト: CS-SI/QGIS
bool QgsGPXFeatureIterator::fetchFeature( QgsFeature &feature )
{
  feature.setValid( false );

  if ( mClosed )
    return false;

  if ( mRequest.filterType() == QgsFeatureRequest::FilterFid )
  {
    bool res = readFid( feature );
    close();
    if ( res )
      geometryToDestinationCrs( feature, mTransform );
    return res;
  }

  if ( mSource->mFeatureType == QgsGPXProvider::WaypointType )
  {
    // go through the list of waypoints and return the first one that is in
    // the bounds rectangle
    for ( ; mWptIter != mSource->data->waypointsEnd(); ++mWptIter )
    {
      if ( readWaypoint( *mWptIter, feature ) )
      {
        ++mWptIter;
        geometryToDestinationCrs( feature, mTransform );
        return true;
      }
    }
  }
  else if ( mSource->mFeatureType == QgsGPXProvider::RouteType )
  {
    // go through the routes and return the first one that is in the bounds
    // rectangle
    for ( ; mRteIter != mSource->data->routesEnd(); ++mRteIter )
    {
      if ( readRoute( *mRteIter, feature ) )
      {
        ++mRteIter;
        geometryToDestinationCrs( feature, mTransform );
        return true;
      }
    }
  }
  else if ( mSource->mFeatureType == QgsGPXProvider::TrackType )
  {
    // go through the tracks and return the first one that is in the bounds
    // rectangle
    for ( ; mTrkIter != mSource->data->tracksEnd(); ++mTrkIter )
    {
      if ( readTrack( *mTrkIter, feature ) )
      {
        ++mTrkIter;
        geometryToDestinationCrs( feature, mTransform );
        return true;
      }
    }
  }

  close();
  return false;
}