@@ -77,6 +77,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
77
77
addAlgorithm ( new QgsConvexHullAlgorithm () );
78
78
addAlgorithm ( new QgsPromoteToMultipartAlgorithm () );
79
79
addAlgorithm ( new QgsSelectByLocationAlgorithm () );
80
+ addAlgorithm ( new QgsExtractByLocationAlgorithm () );
80
81
}
81
82
82
83
void QgsCentroidAlgorithm::initAlgorithm ( const QVariantMap & )
@@ -1342,15 +1343,6 @@ QgsCollectAlgorithm *QgsCollectAlgorithm::createInstance() const
1342
1343
1343
1344
void QgsSelectByLocationAlgorithm::initAlgorithm ( const QVariantMap & )
1344
1345
{
1345
- QStringList predicates = QStringList () << QObject::tr ( " intersects" )
1346
- << QObject::tr ( " contains" )
1347
- << QObject::tr ( " is disjoint" )
1348
- << QObject::tr ( " equals" )
1349
- << QObject::tr ( " touches" )
1350
- << QObject::tr ( " overlaps" )
1351
- << QObject::tr ( " within" )
1352
- << QObject::tr ( " crosses" );
1353
-
1354
1346
QStringList methods = QStringList () << QObject::tr ( " creating new selection" )
1355
1347
<< QObject::tr ( " adding to current selection" )
1356
1348
<< QObject::tr ( " select within current selection" )
@@ -1362,7 +1354,7 @@ void QgsSelectByLocationAlgorithm::initAlgorithm( const QVariantMap & )
1362
1354
1363
1355
addParameter ( new QgsProcessingParameterEnum ( QStringLiteral ( " PREDICATE" ),
1364
1356
QObject::tr ( " Where the features are (geometric predicate)" ),
1365
- predicates , true , QVariant::fromValue ( QList< int >() << 0 ) ) );
1357
+ predicateOptionsList () , true , QVariant::fromValue ( QList< int >() << 0 ) ) );
1366
1358
1367
1359
addParameter ( new QgsProcessingParameterFeatureSource ( QStringLiteral ( " INTERSECT" ),
1368
1360
QObject::tr ( " By comparing to the features from" ),
@@ -1391,6 +1383,26 @@ QVariantMap QgsSelectByLocationAlgorithm::processAlgorithm( const QVariantMap &p
1391
1383
QgsFeatureSource *intersectSource = parameterAsSource ( parameters, QStringLiteral ( " INTERSECT" ), context );
1392
1384
const QList< int > selectedPredicates = parameterAsEnums ( parameters, QStringLiteral ( " PREDICATE" ), context );
1393
1385
1386
+ QgsFeatureIds selectedIds;
1387
+ auto addToSelection = [&]( const QgsFeature & feature )
1388
+ {
1389
+ selectedIds.insert ( feature.id () );
1390
+ };
1391
+ process ( selectLayer, intersectSource, selectedPredicates, addToSelection, true , feedback );
1392
+
1393
+ selectLayer->selectByIds ( selectedIds, method );
1394
+ QVariantMap results;
1395
+ results.insert ( QStringLiteral ( " OUTPUT" ), parameters.value ( QStringLiteral ( " INPUT" ) ) );
1396
+ return results;
1397
+ }
1398
+
1399
+ void QgsLocationBasedAlgorithm::process ( QgsFeatureSource *targetSource,
1400
+ QgsFeatureSource *intersectSource,
1401
+ const QList< int > &selectedPredicates,
1402
+ std::function < void ( const QgsFeature & ) > handleFeatureFunction,
1403
+ bool onlyRequireTargetIds,
1404
+ QgsFeedback *feedback )
1405
+ {
1394
1406
// build a list of 'reversed' predicates, because in this function
1395
1407
// we actually test the reverse of what the user wants (allowing us
1396
1408
// to prepare geometries and optimise the algorithm)
@@ -1402,10 +1414,10 @@ QVariantMap QgsSelectByLocationAlgorithm::processAlgorithm( const QVariantMap &p
1402
1414
1403
1415
QgsFeatureIds disjointSet;
1404
1416
if ( predicates.contains ( Disjoint ) )
1405
- disjointSet = selectLayer ->allFeatureIds ();
1417
+ disjointSet = targetSource ->allFeatureIds ();
1406
1418
1407
- QgsFeatureIds selectedSet ;
1408
- QgsFeatureRequest request = QgsFeatureRequest ().setSubsetOfAttributes ( QgsAttributeList () ).setDestinationCrs ( selectLayer-> crs () );
1419
+ QgsFeatureIds foundSet ;
1420
+ QgsFeatureRequest request = QgsFeatureRequest ().setSubsetOfAttributes ( QgsAttributeList () ).setDestinationCrs ( targetSource-> sourceCrs () );
1409
1421
QgsFeatureIterator fIt = intersectSource->getFeatures ( request );
1410
1422
double step = intersectSource->featureCount () > 0 ? 100.0 / intersectSource->featureCount () : 1 ;
1411
1423
int current = 0 ;
@@ -1422,15 +1434,18 @@ QVariantMap QgsSelectByLocationAlgorithm::processAlgorithm( const QVariantMap &p
1422
1434
engine->prepareGeometry ();
1423
1435
QgsRectangle bbox = f.geometry ().boundingBox ();
1424
1436
1425
- request = QgsFeatureRequest ().setFlags ( QgsFeatureRequest::NoGeometry ).setFilterRect ( bbox ).setSubsetOfAttributes ( QgsAttributeList () );
1426
- QgsFeatureIterator testFeatureIt = selectLayer->getFeatures ( request );
1437
+ request = QgsFeatureRequest ().setFilterRect ( bbox );
1438
+ if ( onlyRequireTargetIds )
1439
+ request.setFlags ( QgsFeatureRequest::NoGeometry ).setSubsetOfAttributes ( QgsAttributeList () );
1440
+
1441
+ QgsFeatureIterator testFeatureIt = targetSource->getFeatures ( request );
1427
1442
QgsFeature testFeature;
1428
1443
while ( testFeatureIt.nextFeature ( testFeature ) )
1429
1444
{
1430
1445
if ( feedback->isCanceled () )
1431
1446
break ;
1432
1447
1433
- if ( selectedSet .contains ( testFeature.id () ) )
1448
+ if ( foundSet .contains ( testFeature.id () ) )
1434
1449
{
1435
1450
// already added this one, no need for further tests
1436
1451
continue ;
@@ -1470,26 +1485,33 @@ QVariantMap QgsSelectByLocationAlgorithm::processAlgorithm( const QVariantMap &p
1470
1485
break ;
1471
1486
}
1472
1487
if ( isMatch )
1473
- selectedSet.insert ( testFeature.id () );
1488
+ {
1489
+ foundSet.insert ( testFeature.id () );
1490
+ handleFeatureFunction ( testFeature );
1491
+ }
1474
1492
}
1475
1493
1476
1494
}
1477
1495
1478
- feedback->setProgress ( int ( current * step ) );
1496
+ feedback->setProgress ( current * step );
1479
1497
}
1480
1498
1481
1499
if ( predicates.contains ( Disjoint ) )
1482
1500
{
1483
- selectedSet = selectedSet.unite ( disjointSet );
1501
+ disjointSet = disjointSet.subtract ( foundSet );
1502
+ QgsFeatureRequest disjointReq = QgsFeatureRequest ().setFilterFids ( disjointSet );
1503
+ if ( onlyRequireTargetIds )
1504
+ disjointReq.setSubsetOfAttributes ( QgsAttributeList () ).setFlags ( QgsFeatureRequest::NoGeometry );
1505
+ QgsFeatureIterator disjointIt = targetSource->getFeatures ( disjointReq );
1506
+ QgsFeature f;
1507
+ while ( disjointIt.nextFeature ( f ) )
1508
+ {
1509
+ handleFeatureFunction ( f );
1510
+ }
1484
1511
}
1485
-
1486
- selectLayer->selectByIds ( selectedSet, method );
1487
- QVariantMap results;
1488
- results.insert ( QStringLiteral ( " OUTPUT" ), parameters.value ( QStringLiteral ( " INPUT" ) ) );
1489
- return results;
1490
1512
}
1491
1513
1492
- QgsSelectByLocationAlgorithm ::Predicate QgsSelectByLocationAlgorithm ::reversePredicate ( QgsSelectByLocationAlgorithm ::Predicate predicate ) const
1514
+ QgsLocationBasedAlgorithm ::Predicate QgsLocationBasedAlgorithm ::reversePredicate ( QgsLocationBasedAlgorithm ::Predicate predicate ) const
1493
1515
{
1494
1516
switch ( predicate )
1495
1517
{
@@ -1514,8 +1536,71 @@ QgsSelectByLocationAlgorithm::Predicate QgsSelectByLocationAlgorithm::reversePre
1514
1536
return Intersects;
1515
1537
}
1516
1538
1539
+ QStringList QgsLocationBasedAlgorithm::predicateOptionsList () const
1540
+ {
1541
+ return QStringList () << QObject::tr ( " intersects" )
1542
+ << QObject::tr ( " contains" )
1543
+ << QObject::tr ( " is disjoint" )
1544
+ << QObject::tr ( " equals" )
1545
+ << QObject::tr ( " touches" )
1546
+ << QObject::tr ( " overlaps" )
1547
+ << QObject::tr ( " within" )
1548
+ << QObject::tr ( " crosses" );
1549
+ }
1550
+
1517
1551
1518
1552
1519
- // /@endcond
1553
+ void QgsExtractByLocationAlgorithm::initAlgorithm ( const QVariantMap & )
1554
+ {
1555
+ addParameter ( new QgsProcessingParameterVectorLayer ( QStringLiteral ( " INPUT" ), QObject::tr ( " Extract features from" ),
1556
+ QList< int >() << QgsProcessing::TypeVectorAnyGeometry ) );
1557
+
1558
+ addParameter ( new QgsProcessingParameterEnum ( QStringLiteral ( " PREDICATE" ),
1559
+ QObject::tr ( " Where the features are (geometric predicate)" ),
1560
+ predicateOptionsList (), true , QVariant::fromValue ( QList< int >() << 0 ) ) );
1520
1561
1562
+ addParameter ( new QgsProcessingParameterFeatureSource ( QStringLiteral ( " INTERSECT" ),
1563
+ QObject::tr ( " By comparing to the features from" ),
1564
+ QList< int >() << QgsProcessing::TypeVectorAnyGeometry ) );
1565
+
1566
+ addParameter ( new QgsProcessingParameterFeatureSink ( QStringLiteral ( " OUTPUT" ), QObject::tr ( " Extracted (location)" ) ) );
1567
+ }
1568
+
1569
+ QString QgsExtractByLocationAlgorithm::shortHelpString () const
1570
+ {
1571
+ return QObject::tr ( " This algorithm creates a new vector layer that only contains matching features from an "
1572
+ " input layer. The criteria for adding features to the resulting layer is defined "
1573
+ " based on the spatial relationship between each feature and the features in an additional layer." );
1574
+ }
1575
+
1576
+ QgsExtractByLocationAlgorithm *QgsExtractByLocationAlgorithm::createInstance () const
1577
+ {
1578
+ return new QgsExtractByLocationAlgorithm ();
1579
+ }
1580
+
1581
+ QVariantMap QgsExtractByLocationAlgorithm::processAlgorithm ( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
1582
+ {
1583
+ QgsFeatureSource *input = parameterAsSource ( parameters, QStringLiteral ( " INPUT" ), context );
1584
+ QgsFeatureSource *intersectSource = parameterAsSource ( parameters, QStringLiteral ( " INTERSECT" ), context );
1585
+ const QList< int > selectedPredicates = parameterAsEnums ( parameters, QStringLiteral ( " PREDICATE" ), context );
1586
+ QString dest;
1587
+ std::unique_ptr< QgsFeatureSink > sink ( parameterAsSink ( parameters, QStringLiteral ( " OUTPUT" ), context, dest, input->fields (), input->wkbType (), input->sourceCrs () ) );
1588
+
1589
+ if ( !sink )
1590
+ return QVariantMap ();
1591
+
1592
+ auto addToSink = [&]( const QgsFeature & feature )
1593
+ {
1594
+ QgsFeature f = feature;
1595
+ sink->addFeature ( f, QgsFeatureSink::FastInsert );
1596
+ };
1597
+ process ( input, intersectSource, selectedPredicates, addToSink, true , feedback );
1598
+
1599
+ QVariantMap results;
1600
+ results.insert ( QStringLiteral ( " OUTPUT" ), dest );
1601
+ return results;
1602
+ }
1603
+
1604
+
1605
+ // /@endcond
1521
1606
0 commit comments