bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature ) const
{
  feature.setFeatureId( OGR_F_GetFID( fet ) );
  feature.initAttributes( mSource->mFields.count() );
  feature.setFields( mSource->mFields ); // allow name-based attribute lookups

  bool useIntersect = mRequest.flags() & QgsFeatureRequest::ExactIntersect;
  bool geometryTypeFilter = mSource->mOgrGeometryTypeFilter != wkbUnknown;
  if ( mFetchGeometry || useIntersect || geometryTypeFilter )
  {
    OGRGeometryH geom = OGR_F_GetGeometryRef( fet );

    if ( geom )
    {
      feature.setGeometry( QgsOgrUtils::ogrGeometryToQgsGeometry( geom ) );
    }
    else
      feature.clearGeometry();

    if ( mSource->mOgrGeometryTypeFilter == wkbGeometryCollection &&
         geom && wkbFlatten( OGR_G_GetGeometryType( geom ) ) == wkbGeometryCollection )
    {
      // OK
    }
    else if (( useIntersect && ( !feature.hasGeometry() || !feature.geometry().intersects( mRequest.filterRect() ) ) )
             || ( geometryTypeFilter && ( !feature.hasGeometry() || QgsOgrProvider::ogrWkbSingleFlatten(( OGRwkbGeometryType )feature.geometry().wkbType() ) != mSource->mOgrGeometryTypeFilter ) ) )
    {
      OGR_F_Destroy( fet );
      return false;
    }
  }

  if ( !mFetchGeometry )
  {
    feature.clearGeometry();
  }

  // fetch attributes
  if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes )
  {
    QgsAttributeList attrs = mRequest.subsetOfAttributes();
    for ( QgsAttributeList::const_iterator it = attrs.begin(); it != attrs.end(); ++it )
    {
      getFeatureAttribute( fet, feature, *it );
    }
  }
  else
  {
    // all attributes
    for ( int idx = 0; idx < mSource->mFields.count(); ++idx )
    {
      getFeatureAttribute( fet, feature, idx );
    }
  }

  return true;
}
QgsFeatureList QgsConvexHullAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback *feedback )
{
  QgsFeature f = feature;
  if ( f.hasGeometry() )
  {
    QgsGeometry outputGeometry;
    if ( QgsWkbTypes::flatType( f.geometry().wkbType() ) == QgsWkbTypes::Point )
    {
      feedback->reportError( QObject::tr( "Cannot calculate convex hull for a single Point feature (try 'Minimum bounding geometry' algorithm instead)." ) );
      f.clearGeometry();
    }
    else
    {
      outputGeometry = f.geometry().convexHull();
      if ( outputGeometry.isNull() )
        feedback->reportError( outputGeometry.lastError() );
      f.setGeometry( outputGeometry );
    }
    if ( !outputGeometry.isNull() )
    {
      QgsAttributes attrs = f.attributes();
      attrs << outputGeometry.constGet()->area()
            << outputGeometry.constGet()->perimeter();
      f.setAttributes( attrs );
    }
    else
    {
      QgsAttributes attrs = f.attributes();
      attrs << QVariant()
            << QVariant();
      f.setAttributes( attrs );
    }
  }
  return QgsFeatureList() << f;
}
Exemple #3
0
bool QgsOgrUtils::readOgrFeatureGeometry( OGRFeatureH ogrFet, QgsFeature& feature )
{
  if ( !ogrFet )
    return false;

  OGRGeometryH geom = OGR_F_GetGeometryRef( ogrFet );
  if ( !geom )
    feature.clearGeometry();
  else
    feature.setGeometry( ogrGeometryToQgsGeometry( geom ) );

  return true;
}
Exemple #4
0
QgsFeatureList QgsBoundaryAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback *feedback )
{
  QgsFeature outFeature = feature;

  if ( feature.hasGeometry() )
  {
    QgsGeometry inputGeometry = feature.geometry();
    QgsGeometry outputGeometry = QgsGeometry( inputGeometry.constGet()->boundary() );
    if ( !outputGeometry )
    {
      feedback->reportError( QObject::tr( "No boundary for feature %1 (possibly a closed linestring?)'" ).arg( feature.id() ) );
      outFeature.clearGeometry();
    }
    else
    {
      outFeature.setGeometry( outputGeometry );
    }
  }
  return QgsFeatureList() << outFeature;
}
QgsFeatureList QgsLineSubstringAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback * )
{
  QgsFeature f = feature;
  if ( f.hasGeometry() )
  {
    const QgsGeometry geometry = f.geometry();
    double startDistance = mStartDistance;
    if ( mDynamicStartDistance )
      startDistance = mStartDistanceProperty.valueAsDouble( context.expressionContext(), startDistance );

    double endDistance = mEndDistance;
    if ( mDynamicEndDistance )
      endDistance = mEndDistanceProperty.valueAsDouble( context.expressionContext(), endDistance );

    const QgsCurve *curve = nullptr;
    if ( !geometry.isMultipart() )
      curve = qgsgeometry_cast< const QgsCurve * >( geometry.constGet() );
    else
    {
      if ( const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( geometry.constGet() ) )
      {
        if ( collection->numGeometries() > 0 )
        {
          curve = qgsgeometry_cast< const QgsCurve * >( collection->geometryN( 0 ) );
        }
      }
    }
    if ( curve )
    {
      std::unique_ptr< QgsCurve > substring( curve->curveSubstring( startDistance, endDistance ) );
      QgsGeometry result( std::move( substring ) );
      f.setGeometry( result );
    }
    else
    {
      f.clearGeometry();
    }
  }
  return QgsFeatureList() << f;
}
Exemple #6
0
void QgsAbstractFeatureIterator::geometryToDestinationCrs( QgsFeature &feature, const QgsCoordinateTransform &transform ) const
{
  if ( transform.isValid() && feature.hasGeometry() )
  {
    try
    {
      QgsGeometry g = feature.geometry();
      g.transform( transform );
      feature.setGeometry( g );
    }
    catch ( QgsCsException & )
    {
      // transform error
      if ( mRequest.transformErrorCallback() )
      {
        mRequest.transformErrorCallback()( feature );
      }
      // remove geometry - we can't reproject so better not return a geometry in a different crs
      feature.clearGeometry();
    }
  }
}
QgsFeature QgsTransformAlgorithm::processFeature( const QgsFeature &f, QgsProcessingContext &, QgsProcessingFeedback * )
{
  QgsFeature feature = f;
  if ( !mCreatedTransform )
  {
    mCreatedTransform = true;
    mTransform = QgsCoordinateTransform( sourceCrs(), mDestCrs, mTransformContext );
  }

  if ( feature.hasGeometry() )
  {
    QgsGeometry g = feature.geometry();
    if ( g.transform( mTransform ) == 0 )
    {
      feature.setGeometry( g );
    }
    else
    {
      feature.clearGeometry();
    }
  }
  return feature;
}
QgsFeature QgsFixGeometriesAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingFeedback *feedback )
{
  if ( !feature.hasGeometry() )
    return feature;

  QgsFeature outputFeature = feature;

  QgsGeometry outputGeometry = outputFeature.geometry().makeValid();
  if ( !outputGeometry )
  {
    feedback->pushInfo( QObject::tr( "makeValid failed for feature %1 " ).arg( feature.id() ) );
    outputFeature.clearGeometry();
    return outputFeature;
  }

  if ( outputGeometry.wkbType() == QgsWkbTypes::Unknown ||
       QgsWkbTypes::flatType( outputGeometry.wkbType() ) == QgsWkbTypes::GeometryCollection )
  {
    // keep only the parts of the geometry collection with correct type
    const QVector< QgsGeometry > tmpGeometries = outputGeometry.asGeometryCollection();
    QVector< QgsGeometry > matchingParts;
    for ( const QgsGeometry &g : tmpGeometries )
    {
      if ( g.type() == feature.geometry().type() )
        matchingParts << g;
    }
    if ( !matchingParts.empty() )
      outputGeometry = QgsGeometry::collectGeometry( matchingParts );
    else
      outputGeometry = QgsGeometry();
  }

  outputGeometry.convertToMultiType();
  outputFeature.setGeometry( outputGeometry );
  return outputFeature;
}
QVariantMap QgsShortestPathPointToLayerAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
  loadCommonParams( parameters, context, feedback );

  QgsPointXY startPoint = parameterAsPoint( parameters, QStringLiteral( "START_POINT" ), context, mNetwork->sourceCrs() );

  std::unique_ptr< QgsFeatureSource > endPoints( parameterAsSource( parameters, QStringLiteral( "END_POINTS" ), context ) );
  if ( !endPoints )
    throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "END_POINTS" ) ) );

  QgsFields fields = endPoints->fields();
  fields.append( QgsField( QStringLiteral( "start" ), QVariant::String ) );
  fields.append( QgsField( QStringLiteral( "end" ), QVariant::String ) );
  fields.append( QgsField( QStringLiteral( "cost" ), QVariant::Double ) );

  QString dest;
  std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, QgsWkbTypes::LineString, mNetwork->sourceCrs() ) );
  if ( !sink )
    throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );

  QVector< QgsPointXY > points;
  points.push_front( startPoint );
  QHash< int, QgsAttributes > sourceAttributes;
  loadPoints( endPoints.get(), points, sourceAttributes, context, feedback );

  feedback->pushInfo( QObject::tr( "Building graph…" ) );
  QVector< QgsPointXY > snappedPoints;
  mDirector->makeGraph( mBuilder.get(), points, snappedPoints, feedback );

  feedback->pushInfo( QObject::tr( "Calculating shortest paths…" ) );
  QgsGraph *graph = mBuilder->graph();
  int idxStart = graph->findVertex( snappedPoints[0] );
  int idxEnd;

  QVector< int > tree;
  QVector< double > costs;
  QgsGraphAnalyzer::dijkstra( graph, idxStart, 0, &tree, &costs );

  QVector<QgsPointXY> route;
  double cost;

  QgsFeature feat;
  feat.setFields( fields );
  QgsAttributes attributes;

  int step =  points.size() > 0 ? 100.0 / points.size() : 1;
  for ( int i = 1; i < points.size(); i++ )
  {
    if ( feedback->isCanceled() )
    {
      break;
    }

    idxEnd = graph->findVertex( snappedPoints[i] );
    if ( tree.at( idxEnd ) == -1 )
    {
      feedback->reportError( QObject::tr( "There is no route from start point (%1) to end point (%2)." )
                             .arg( startPoint.toString(),
                                   points[i].toString() ) );
      feat.clearGeometry();
      attributes = sourceAttributes.value( i );
      attributes.append( QVariant() );
      attributes.append( points[i].toString() );
      feat.setAttributes( attributes );
      sink->addFeature( feat, QgsFeatureSink::FastInsert );
      continue;
    }

    route.clear();
    route.push_front( graph->vertex( idxEnd ).point() );
    cost = costs.at( idxEnd );
    while ( idxEnd != idxStart )
    {
      idxEnd = graph->edge( tree.at( idxEnd ) ).fromVertex();
      route.push_front( graph->vertex( idxEnd ).point() );
    }

    QgsGeometry geom = QgsGeometry::fromPolylineXY( route );
    QgsFeature feat;
    feat.setFields( fields );
    attributes = sourceAttributes.value( i );
    attributes.append( startPoint.toString() );
    attributes.append( points[i].toString() );
    attributes.append( cost / mMultiplier );
    feat.setAttributes( attributes );
    feat.setGeometry( geom );
    sink->addFeature( feat, QgsFeatureSink::FastInsert );

    feedback->setProgress( i * step );
  }

  QVariantMap outputs;
  outputs.insert( QStringLiteral( "OUTPUT" ), dest );
  return outputs;
}
QgsFeature QgsDropGeometryAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingFeedback * )
{
  QgsFeature f = feature;
  f.clearGeometry();
  return f;
}
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;
}
QgsFeatureList QgsDropGeometryAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * )
{
  QgsFeature f = feature;
  f.clearGeometry();
  return QgsFeatureList() << f;
}
bool QgsOgrFeatureIterator::readFeature( gdal::ogr_feature_unique_ptr fet, QgsFeature &feature ) const
{
  feature.setId( OGR_F_GetFID( fet.get() ) );
  feature.initAttributes( mSource->mFields.count() );
  feature.setFields( mSource->mFields ); // allow name-based attribute lookups

  bool useIntersect = !mRequest.filterRect().isNull();
  bool geometryTypeFilter = mSource->mOgrGeometryTypeFilter != wkbUnknown;
  if ( mFetchGeometry || useIntersect || geometryTypeFilter )
  {
    OGRGeometryH geom = OGR_F_GetGeometryRef( fet.get() );

    if ( geom )
    {
      QgsGeometry g = QgsOgrUtils::ogrGeometryToQgsGeometry( geom );

      // Insure that multipart datasets return multipart geometry
      if ( QgsWkbTypes::isMultiType( mSource->mWkbType ) && !g.isMultipart() )
      {
        g.convertToMultiType();
      }

      feature.setGeometry( g );
    }
    else
      feature.clearGeometry();

    if ( mSource->mOgrGeometryTypeFilter == wkbGeometryCollection &&
         geom && wkbFlatten( OGR_G_GetGeometryType( geom ) ) == wkbGeometryCollection )
    {
      // OK
    }
    else if ( ( useIntersect && ( !feature.hasGeometry()
                                  || ( mRequest.flags() & QgsFeatureRequest::ExactIntersect && !feature.geometry().intersects( mFilterRect ) )
                                  || ( !( mRequest.flags() & QgsFeatureRequest::ExactIntersect ) && !feature.geometry().boundingBoxIntersects( mFilterRect ) )
                                )
              )
              || ( geometryTypeFilter && ( !feature.hasGeometry() || QgsOgrProvider::ogrWkbSingleFlatten( ( OGRwkbGeometryType )feature.geometry().wkbType() ) != mSource->mOgrGeometryTypeFilter ) ) )
    {
      return false;
    }
  }

  if ( !mFetchGeometry )
  {
    feature.clearGeometry();
  }

  // fetch attributes
  if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes )
  {
    QgsAttributeList attrs = mRequest.subsetOfAttributes();
    for ( QgsAttributeList::const_iterator it = attrs.constBegin(); it != attrs.constEnd(); ++it )
    {
      getFeatureAttribute( fet.get(), feature, *it );
    }
  }
  else
  {
    // all attributes
    const auto fieldCount = mSource->mFields.count();
    for ( int idx = 0; idx < fieldCount; ++idx )
    {
      getFeatureAttribute( fet.get(), feature, idx );
    }
  }

  return true;
}