LCOV - code coverage report
Current view: top level - analysis/processing - qgsalgorithmlineintersection.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 0 115 0.0 %
Date: 2021-04-10 08:29:14 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :                          qgsalgorithmlineintersection.cpp
       3                 :            :                          ---------------------
       4                 :            :     begin                : April 2017
       5                 :            :     copyright            : (C) 2017 by Nyall Dawson
       6                 :            :     email                : nyall dot dawson at gmail dot com
       7                 :            :  ***************************************************************************/
       8                 :            : 
       9                 :            : /***************************************************************************
      10                 :            :  *                                                                         *
      11                 :            :  *   This program is free software; you can redistribute it and/or modify  *
      12                 :            :  *   it under the terms of the GNU General Public License as published by  *
      13                 :            :  *   the Free Software Foundation; either version 2 of the License, or     *
      14                 :            :  *   (at your option) any later version.                                   *
      15                 :            :  *                                                                         *
      16                 :            :  ***************************************************************************/
      17                 :            : 
      18                 :            : #include "qgsalgorithmlineintersection.h"
      19                 :            : #include "qgsgeometryengine.h"
      20                 :            : 
      21                 :            : ///@cond PRIVATE
      22                 :            : 
      23                 :          0 : QString QgsLineIntersectionAlgorithm::name() const
      24                 :            : {
      25                 :          0 :   return QStringLiteral( "lineintersections" );
      26                 :            : }
      27                 :            : 
      28                 :          0 : QString QgsLineIntersectionAlgorithm::displayName() const
      29                 :            : {
      30                 :          0 :   return QObject::tr( "Line intersections" );
      31                 :            : }
      32                 :            : 
      33                 :          0 : QStringList QgsLineIntersectionAlgorithm::tags() const
      34                 :            : {
      35                 :          0 :   return QObject::tr( "line,intersection" ).split( ',' );
      36                 :          0 : }
      37                 :            : 
      38                 :          0 : QString QgsLineIntersectionAlgorithm::group() const
      39                 :            : {
      40                 :          0 :   return QObject::tr( "Vector overlay" );
      41                 :            : }
      42                 :            : 
      43                 :          0 : QString QgsLineIntersectionAlgorithm::groupId() const
      44                 :            : {
      45                 :          0 :   return QStringLiteral( "vectoroverlay" );
      46                 :            : }
      47                 :            : 
      48                 :          0 : void QgsLineIntersectionAlgorithm::initAlgorithm( const QVariantMap & )
      49                 :            : {
      50                 :          0 :   addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ),
      51                 :          0 :                 QObject::tr( "Input layer" ), QList< int >() << QgsProcessing::TypeVectorLine ) );
      52                 :          0 :   addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INTERSECT" ),
      53                 :          0 :                 QObject::tr( "Intersect layer" ), QList< int >() << QgsProcessing::TypeVectorLine ) );
      54                 :            : 
      55                 :          0 :   addParameter( new QgsProcessingParameterField(
      56                 :          0 :                   QStringLiteral( "INPUT_FIELDS" ),
      57                 :          0 :                   QObject::tr( "Input fields to keep (leave empty to keep all fields)" ), QVariant(),
      58                 :          0 :                   QStringLiteral( "INPUT" ), QgsProcessingParameterField::Any,
      59                 :            :                   true, true ) );
      60                 :          0 :   addParameter( new QgsProcessingParameterField(
      61                 :          0 :                   QStringLiteral( "INTERSECT_FIELDS" ),
      62                 :          0 :                   QObject::tr( "Intersect fields to keep (leave empty to keep all fields)" ), QVariant(),
      63                 :          0 :                   QStringLiteral( "INTERSECT" ), QgsProcessingParameterField::Any,
      64                 :            :                   true, true ) );
      65                 :            : 
      66                 :          0 :   std::unique_ptr< QgsProcessingParameterString > prefix = std::make_unique< QgsProcessingParameterString >( QStringLiteral( "INTERSECT_FIELDS_PREFIX" ), QObject::tr( "Intersect fields prefix" ), QString(), false, true );
      67                 :          0 :   prefix->setFlags( prefix->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
      68                 :          0 :   addParameter( prefix.release() );
      69                 :            : 
      70                 :          0 :   addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Intersections" ), QgsProcessing::TypeVectorPoint ) );
      71                 :          0 : }
      72                 :            : 
      73                 :          0 : QString QgsLineIntersectionAlgorithm::shortHelpString() const
      74                 :            : {
      75                 :          0 :   return QObject::tr( "This algorithm creates point features where the lines in the Intersect layer intersect the lines in the Input layer." );
      76                 :            : }
      77                 :            : 
      78                 :          0 : QgsLineIntersectionAlgorithm *QgsLineIntersectionAlgorithm::createInstance() const
      79                 :            : {
      80                 :          0 :   return new QgsLineIntersectionAlgorithm();
      81                 :            : }
      82                 :            : 
      83                 :          0 : QVariantMap QgsLineIntersectionAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
      84                 :            : {
      85                 :          0 :   std::unique_ptr< QgsFeatureSource > sourceA( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
      86                 :          0 :   if ( !sourceA )
      87                 :          0 :     throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
      88                 :            : 
      89                 :          0 :   std::unique_ptr< QgsFeatureSource > sourceB( parameterAsSource( parameters, QStringLiteral( "INTERSECT" ), context ) );
      90                 :          0 :   if ( !sourceB )
      91                 :          0 :     throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INTERSECT" ) ) );
      92                 :            : 
      93                 :          0 :   const QStringList fieldsA = parameterAsFields( parameters, QStringLiteral( "INPUT_FIELDS" ), context );
      94                 :          0 :   const QStringList fieldsB = parameterAsFields( parameters, QStringLiteral( "INTERSECT_FIELDS" ), context );
      95                 :            : 
      96                 :          0 :   QgsAttributeList fieldIndicesA = QgsProcessingUtils::fieldNamesToIndices( fieldsA, sourceA->fields() );
      97                 :          0 :   QgsAttributeList fieldIndicesB = QgsProcessingUtils::fieldNamesToIndices( fieldsB, sourceB->fields() );
      98                 :            : 
      99                 :          0 :   QString intersectFieldsPrefix = parameterAsString( parameters, QStringLiteral( "INTERSECT_FIELDS_PREFIX" ), context );
     100                 :          0 :   QgsFields outFields = QgsProcessingUtils::combineFields(
     101                 :          0 :                           QgsProcessingUtils::indicesToFields( fieldIndicesA, sourceA->fields() ),
     102                 :          0 :                           QgsProcessingUtils::indicesToFields( fieldIndicesB, sourceB->fields() ),
     103                 :            :                           intersectFieldsPrefix );
     104                 :            : 
     105                 :          0 :   QString dest;
     106                 :          0 :   std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, outFields, QgsWkbTypes::Point,  sourceA->sourceCrs(), QgsFeatureSink::RegeneratePrimaryKey ) );
     107                 :          0 :   if ( !sink )
     108                 :          0 :     throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
     109                 :            : 
     110                 :          0 :   QgsSpatialIndex spatialIndex( sourceB->getFeatures( QgsFeatureRequest().setNoAttributes().setDestinationCrs( sourceA->sourceCrs(), context.transformContext() ) ), feedback );
     111                 :          0 :   QgsFeature outFeature;
     112                 :          0 :   QgsFeatureIterator features = sourceA->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( fieldIndicesA ) );
     113                 :          0 :   double step = sourceA->featureCount() > 0 ? 100.0 / sourceA->featureCount() : 1;
     114                 :          0 :   int i = 0;
     115                 :          0 :   QgsFeature inFeatureA;
     116                 :          0 :   while ( features.nextFeature( inFeatureA ) )
     117                 :            :   {
     118                 :          0 :     i++;
     119                 :          0 :     if ( feedback->isCanceled() )
     120                 :            :     {
     121                 :          0 :       break;
     122                 :            :     }
     123                 :            : 
     124                 :          0 :     if ( !inFeatureA.hasGeometry() )
     125                 :          0 :       continue;
     126                 :            : 
     127                 :          0 :     QgsGeometry inGeom = inFeatureA.geometry();
     128                 :          0 :     QgsFeatureIds lines = qgis::listToSet( spatialIndex.intersects( inGeom.boundingBox() ) );
     129                 :          0 :     if ( !lines.empty() )
     130                 :            :     {
     131                 :            :       // use prepared geometries for faster intersection tests
     132                 :          0 :       std::unique_ptr< QgsGeometryEngine > engine( QgsGeometry::createGeometryEngine( inGeom.constGet() ) );
     133                 :          0 :       engine->prepareGeometry();
     134                 :            : 
     135                 :          0 :       QgsFeatureRequest request = QgsFeatureRequest().setFilterFids( lines );
     136                 :          0 :       request.setDestinationCrs( sourceA->sourceCrs(), context.transformContext() );
     137                 :          0 :       request.setSubsetOfAttributes( fieldIndicesB );
     138                 :            : 
     139                 :          0 :       QgsFeature inFeatureB;
     140                 :          0 :       QgsFeatureIterator featuresB = sourceB->getFeatures( request );
     141                 :          0 :       while ( featuresB.nextFeature( inFeatureB ) )
     142                 :            :       {
     143                 :          0 :         if ( feedback->isCanceled() )
     144                 :            :         {
     145                 :          0 :           break;
     146                 :            :         }
     147                 :            : 
     148                 :          0 :         QgsGeometry tmpGeom = inFeatureB.geometry();
     149                 :          0 :         if ( engine->intersects( tmpGeom.constGet() ) )
     150                 :            :         {
     151                 :          0 :           QgsMultiPointXY points;
     152                 :          0 :           QgsGeometry intersectGeom = inGeom.intersection( tmpGeom );
     153                 :          0 :           QgsAttributes outAttributes;
     154                 :          0 :           for ( int a : std::as_const( fieldIndicesA ) )
     155                 :            :           {
     156                 :          0 :             outAttributes.append( inFeatureA.attribute( a ) );
     157                 :            :           }
     158                 :          0 :           for ( int b : std::as_const( fieldIndicesB ) )
     159                 :            :           {
     160                 :          0 :             outAttributes.append( inFeatureB.attribute( b ) );
     161                 :            :           }
     162                 :          0 :           if ( QgsWkbTypes::flatType( intersectGeom.wkbType() ) == QgsWkbTypes::GeometryCollection )
     163                 :            :           {
     164                 :          0 :             const QVector<QgsGeometry> geomCollection = intersectGeom.asGeometryCollection();
     165                 :          0 :             for ( const QgsGeometry &part : geomCollection )
     166                 :            :             {
     167                 :          0 :               if ( part.type() == QgsWkbTypes::PointGeometry )
     168                 :            :               {
     169                 :          0 :                 if ( part.isMultipart() )
     170                 :            :                 {
     171                 :          0 :                   points = part.asMultiPoint();
     172                 :          0 :                 }
     173                 :            :                 else
     174                 :            :                 {
     175                 :          0 :                   points.append( part.asPoint() );
     176                 :            :                 }
     177                 :          0 :               }
     178                 :            :             }
     179                 :          0 :           }
     180                 :          0 :           else if ( intersectGeom.type() == QgsWkbTypes::PointGeometry )
     181                 :            :           {
     182                 :          0 :             if ( intersectGeom.isMultipart() )
     183                 :            :             {
     184                 :          0 :               points = intersectGeom.asMultiPoint();
     185                 :          0 :             }
     186                 :            :             else
     187                 :            :             {
     188                 :          0 :               points.append( intersectGeom.asPoint() );
     189                 :            :             }
     190                 :          0 :           }
     191                 :          0 :           for ( const QgsPointXY &j : std::as_const( points ) )
     192                 :            :           {
     193                 :          0 :             outFeature.setGeometry( QgsGeometry::fromPointXY( j ) );
     194                 :          0 :             outFeature.setAttributes( outAttributes );
     195                 :          0 :             sink->addFeature( outFeature, QgsFeatureSink::FastInsert );
     196                 :            :           }
     197                 :          0 :         }
     198                 :          0 :       }
     199                 :          0 :     }
     200                 :            : 
     201                 :          0 :     feedback->setProgress( i * step );
     202                 :            : 
     203                 :          0 :   }
     204                 :            : 
     205                 :          0 :   QVariantMap outputs;
     206                 :          0 :   outputs.insert( QStringLiteral( "OUTPUT" ), dest );
     207                 :          0 :   return outputs;
     208                 :          0 : }
     209                 :            : 
     210                 :            : ///@endcond
     211                 :            : 
     212                 :            : 

Generated by: LCOV version 1.14