[{"data":1,"prerenderedAt":1695},["ShallowReactive",2],{"doc:\u002Fspatial-data-processing-automation\u002Fvector-data-manipulation\u002Fselect-features-by-location-pyqgis":3},{"id":4,"title":5,"body":6,"description":1684,"extension":1685,"meta":1686,"navigation":270,"path":1691,"seo":1692,"stem":1693,"__hash__":1694},"docs\u002Fspatial-data-processing-automation\u002Fvector-data-manipulation\u002Fselect-features-by-location-pyqgis\u002Findex.md","Select Features by Location in PyQGIS",{"type":7,"value":8,"toc":1672},"minimark",[9,13,27,36,193,198,220,224,230,492,527,531,534,632,897,922,929,933,940,1113,1128,1196,1200,1203,1485,1506,1510,1526,1530,1570,1574,1583,1587,1597,1603,1613,1623,1633,1637,1668],[10,11,5],"h1",{"id":12},"select-features-by-location-in-pyqgis",[14,15,16,17,21,22,26],"p",{},"\"Which buildings are inside the flood zone?\", \"which roads cross the county boundary?\", \"which wells are ",[18,19,20],"em",{},"not"," within any protected area?\" — selection by location is the spatial counterpart to a ",[23,24,25],"code",{},"WHERE"," clause, and it is often the first step of a larger job: select, then count, export, edit or style what was selected. QGIS ships two algorithms for it, one that changes a layer's selection and one that writes the matching features out, plus the geometry predicates underneath both for when you need something neither algorithm does.",[14,28,29,30,35],{},"This recipe belongs to ",[31,32,34],"a",{"href":33},"\u002Fspatial-data-processing-automation\u002Fvector-data-manipulation\u002F","Vector Data Manipulation in PyQGIS",". It runs both algorithms, explains how the predicate codes map to real relationships, combines spatial selections with existing ones, and reproduces the selection in Python with a spatial index.",[14,37,38],{},[39,40,45,49,53,60,69,78,85,92,98,105,110,117,122,125,130,134,140,143,147,155,161,164,167,171,174,176,180,183,185,188,191],"svg",{"viewBox":41,"role":42,"ariaLabel":43,"xmlns":44},"0 0 760 300","img","The most used spatial predicates illustrated with a polygon and candidate features: intersects catches anything touching or overlapping, within catches only features entirely inside, touches catches only boundary contact, disjoint catches features with no contact","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg",[46,47,48],"title",{},"Which features does each predicate select?",[50,51,52],"desc",{},"A flood zone polygon with four buildings: A entirely inside, B straddling the boundary, C sharing only an edge with the zone, and D well outside. Intersects selects A, B and C. Are within selects only A. Touches selects only C. Disjoint selects only D. Choosing the predicate is choosing which of these counts as in.",[54,55],"rect",{"x":56,"y":56,"width":57,"height":58,"fill":59},"0","760","300","#f6f3ea",[61,62,68],"text",{"x":63,"y":64,"style":65,"fill":66,"textAnchor":67},"380","28","text-anchor:middle;font-size:14px;font-weight:bold;font-family:sans-serif","#17211d","middle","Four buildings, four different answers",[54,70],{"x":71,"y":72,"width":58,"height":73,"rx":74,"fill":75,"stroke":76,"style":77},"24","48","230","10","#fffdf7","#59645f","stroke-width:2",[79,80],"path",{"d":81,"fill":82,"stroke":83,"style":84},"M60 90 L260 80 L280 230 L70 240 z","#dbeafe","#2563eb","stroke-width:2.5",[54,86],{"x":87,"y":88,"width":89,"height":90,"fill":91},"110","130","46","36","#15803d",[61,93,97],{"x":94,"y":95,"style":96,"fill":75,"textAnchor":67},"133","153","text-anchor:middle;font-size:11px;font-weight:bold;font-family:sans-serif","A",[54,99],{"x":100,"y":101,"width":102,"height":103,"fill":104},"245","120","52","40","#b45309",[61,106,109],{"x":107,"y":108,"style":96,"fill":75,"textAnchor":67},"271","145","B",[54,111],{"x":112,"y":113,"width":114,"height":115,"fill":116},"150","240","50","30","#0f766e",[61,118,121],{"x":119,"y":120,"style":96,"fill":75,"textAnchor":67},"175","260","C",[54,123],{"x":90,"y":124,"width":115,"height":71,"fill":76},"56",[61,126,129],{"x":127,"y":128,"style":96,"fill":75,"textAnchor":67},"51","73","D",[54,131],{"x":132,"y":72,"width":133,"height":73,"rx":74,"fill":75,"stroke":76,"style":77},"348","388",[61,135,139],{"x":136,"y":137,"style":138,"fill":66,"textAnchor":67},"440","80","text-anchor:middle;font-size:10.5px;font-weight:bold;font-family:sans-serif","predicate",[61,141,23],{"x":142,"y":137,"style":138,"fill":66,"textAnchor":67},"560",[61,144,146],{"x":145,"y":137,"style":138,"fill":66,"textAnchor":67},"660","selects",[148,149],"line",{"x1":150,"y1":151,"x2":152,"y2":151,"stroke":153,"style":154},"364","92","720","#d9d3c4","stroke-width:1.5",[61,156,160],{"x":136,"y":157,"style":158,"fill":159,"textAnchor":67},"122","text-anchor:middle;font-size:10.5px;font-family:sans-serif","#2f3b35","intersect",[61,162,56],{"x":142,"y":157,"style":163,"fill":159,"textAnchor":67},"text-anchor:middle;font-size:10.5px;font-family:monospace",[61,165,166],{"x":145,"y":157,"style":138,"fill":159,"textAnchor":67},"A B C",[61,168,170],{"x":136,"y":169,"style":158,"fill":159,"textAnchor":67},"158","are within",[61,172,173],{"x":142,"y":169,"style":163,"fill":159,"textAnchor":67},"6",[61,175,97],{"x":145,"y":169,"style":138,"fill":91,"textAnchor":67},[61,177,179],{"x":136,"y":178,"style":158,"fill":159,"textAnchor":67},"194","touch",[61,181,182],{"x":142,"y":178,"style":163,"fill":159,"textAnchor":67},"4",[61,184,121],{"x":145,"y":178,"style":138,"fill":116,"textAnchor":67},[61,186,187],{"x":136,"y":73,"style":158,"fill":159,"textAnchor":67},"disjoint",[61,189,190],{"x":142,"y":73,"style":163,"fill":159,"textAnchor":67},"2",[61,192,129],{"x":145,"y":73,"style":138,"fill":76,"textAnchor":67},[194,195,197],"h2",{"id":196},"prerequisites","Prerequisites",[199,200,201,209,212],"ul",{},[202,203,204,208],"li",{},[205,206,207],"strong",{},"QGIS 3.40 LTR"," or newer, or the QGIS 4 series.",[202,210,211],{},"Two vector layers. They do not need to share a CRS — the algorithms reproject the comparison layer on the fly — but results are easier to check when they do.",[202,213,214,215,219],{},"Valid geometries in both layers. An invalid polygon can make predicates return nothing; see ",[31,216,218],{"href":217},"\u002Fspatial-data-processing-automation\u002Fgeometry-operations-and-predicates\u002Ffix-invalid-geometries-pyqgis\u002F","finding and fixing invalid geometries",".",[194,221,223],{"id":222},"select-features-that-meet-a-predicate","Select features that meet a predicate",[14,225,226,229],{},[23,227,228],{},"native:selectbylocation"," changes the selection on the input layer in place. It writes nothing to disk, which suits interactive work and scripts that go on to act on the selection.",[231,232,237],"pre",{"className":233,"code":234,"language":235,"meta":236,"style":236},"language-python shiki shiki-themes github-dark","import processing\nfrom qgis.core import QgsProject\n\nbuildings = QgsProject.instance().mapLayersByName(\"buildings\")[0]\nflood = QgsProject.instance().mapLayersByName(\"flood_zone_3\")[0]\n\nINTERSECT, CONTAIN, DISJOINT, EQUAL, TOUCH, OVERLAP, WITHIN, CROSS = range(8)\nNEW, ADD, WITHIN_CURRENT, REMOVE = range(4)\n\nprocessing.run(\"native:selectbylocation\", {\n    \"INPUT\": buildings,\n    \"PREDICATE\": [INTERSECT],\n    \"INTERSECT\": flood,\n    \"METHOD\": NEW,\n})\nprint(buildings.selectedFeatureCount(), \"buildings intersect flood zone 3\")\n","python","",[23,238,239,251,265,272,297,316,321,378,409,414,426,435,449,458,472,478],{"__ignoreMap":236},[240,241,243,247],"span",{"class":148,"line":242},1,[240,244,246],{"class":245},"snl16","import",[240,248,250],{"class":249},"s95oV"," processing\n",[240,252,254,257,260,262],{"class":148,"line":253},2,[240,255,256],{"class":245},"from",[240,258,259],{"class":249}," qgis.core ",[240,261,246],{"class":245},[240,263,264],{"class":249}," QgsProject\n",[240,266,268],{"class":148,"line":267},3,[240,269,271],{"emptyLinePlaceholder":270},true,"\n",[240,273,275,278,281,284,288,291,294],{"class":148,"line":274},4,[240,276,277],{"class":249},"buildings ",[240,279,280],{"class":245},"=",[240,282,283],{"class":249}," QgsProject.instance().mapLayersByName(",[240,285,287],{"class":286},"sU2Wk","\"buildings\"",[240,289,290],{"class":249},")[",[240,292,56],{"class":293},"sDLfK",[240,295,296],{"class":249},"]\n",[240,298,300,303,305,307,310,312,314],{"class":148,"line":299},5,[240,301,302],{"class":249},"flood ",[240,304,280],{"class":245},[240,306,283],{"class":249},[240,308,309],{"class":286},"\"flood_zone_3\"",[240,311,290],{"class":249},[240,313,56],{"class":293},[240,315,296],{"class":249},[240,317,319],{"class":148,"line":318},6,[240,320,271],{"emptyLinePlaceholder":270},[240,322,324,327,330,333,335,338,340,343,345,348,350,353,355,358,360,363,366,369,372,375],{"class":148,"line":323},7,[240,325,326],{"class":293},"INTERSECT",[240,328,329],{"class":249},", ",[240,331,332],{"class":293},"CONTAIN",[240,334,329],{"class":249},[240,336,337],{"class":293},"DISJOINT",[240,339,329],{"class":249},[240,341,342],{"class":293},"EQUAL",[240,344,329],{"class":249},[240,346,347],{"class":293},"TOUCH",[240,349,329],{"class":249},[240,351,352],{"class":293},"OVERLAP",[240,354,329],{"class":249},[240,356,357],{"class":293},"WITHIN",[240,359,329],{"class":249},[240,361,362],{"class":293},"CROSS",[240,364,365],{"class":245}," =",[240,367,368],{"class":293}," range",[240,370,371],{"class":249},"(",[240,373,374],{"class":293},"8",[240,376,377],{"class":249},")\n",[240,379,381,384,386,389,391,394,396,399,401,403,405,407],{"class":148,"line":380},8,[240,382,383],{"class":293},"NEW",[240,385,329],{"class":249},[240,387,388],{"class":293},"ADD",[240,390,329],{"class":249},[240,392,393],{"class":293},"WITHIN_CURRENT",[240,395,329],{"class":249},[240,397,398],{"class":293},"REMOVE",[240,400,365],{"class":245},[240,402,368],{"class":293},[240,404,371],{"class":249},[240,406,182],{"class":293},[240,408,377],{"class":249},[240,410,412],{"class":148,"line":411},9,[240,413,271],{"emptyLinePlaceholder":270},[240,415,417,420,423],{"class":148,"line":416},10,[240,418,419],{"class":249},"processing.run(",[240,421,422],{"class":286},"\"native:selectbylocation\"",[240,424,425],{"class":249},", {\n",[240,427,429,432],{"class":148,"line":428},11,[240,430,431],{"class":286},"    \"INPUT\"",[240,433,434],{"class":249},": buildings,\n",[240,436,438,441,444,446],{"class":148,"line":437},12,[240,439,440],{"class":286},"    \"PREDICATE\"",[240,442,443],{"class":249},": [",[240,445,326],{"class":293},[240,447,448],{"class":249},"],\n",[240,450,452,455],{"class":148,"line":451},13,[240,453,454],{"class":286},"    \"INTERSECT\"",[240,456,457],{"class":249},": flood,\n",[240,459,461,464,467,469],{"class":148,"line":460},14,[240,462,463],{"class":286},"    \"METHOD\"",[240,465,466],{"class":249},": ",[240,468,383],{"class":293},[240,470,471],{"class":249},",\n",[240,473,475],{"class":148,"line":474},15,[240,476,477],{"class":249},"})\n",[240,479,481,484,487,490],{"class":148,"line":480},16,[240,482,483],{"class":293},"print",[240,485,486],{"class":249},"(buildings.selectedFeatureCount(), ",[240,488,489],{"class":286},"\"buildings intersect flood zone 3\"",[240,491,377],{"class":249},[14,493,494,497,498,501,502,505,506,508,509,512,513,516,517,519,520,523,524,526],{},[205,495,496],{},"Breakdown:"," ",[23,499,500],{},"PREDICATE"," is a list of integer codes, and naming them as constants at the top makes the call readable; the order above is the order the algorithm defines. Several predicates in the list are combined with OR, so ",[23,503,504],{},"[WITHIN, OVERLAP]"," selects features that are inside or partly inside. ",[23,507,326],{}," is the comparison layer, which confusingly shares its name with the first predicate. ",[23,510,511],{},"METHOD"," controls how the result combines with the existing selection. The relationship is always read as ",[18,514,515],{},"input predicate comparison"," — buildings ",[18,518,170],{}," the flood zone — which is why ",[18,521,522],{},"contain"," and ",[18,525,170],{}," are not interchangeable.",[194,528,530],{"id":529},"combine-with-existing-selections","Combine with existing selections",[14,532,533],{},"Spatial and attribute selections compose. A common pattern is to narrow down by attribute first, then by location — or to subtract one spatial result from another.",[14,535,536],{},[39,537,540,543,546,549,563,567,571,576,581,586,592,596,599,603,606,610,614,618,621,624,628],{"viewBox":538,"role":42,"ariaLabel":539,"xmlns":44},"0 0 760 256","Selection methods combined in sequence: select residential buildings by expression, keep only those within the flood zone using select within current selection, then remove those within 20 m of a defence using remove from current selection",[46,541,542],{},"Build a selection in steps",[50,544,545],{},"Step one selects 12,400 residential buildings by attribute expression. Step two uses method 2, selecting within the current selection, to keep 1,130 that intersect flood zone 3. Step three uses method 3, removing from the current selection, to drop 210 within 20 metres of a flood defence buffer. The final selection holds 920 buildings.",[54,547],{"x":56,"y":56,"width":57,"height":548,"fill":59},"256",[550,551,552],"defs",{},[553,554,560],"marker",{"id":555,"viewBox":556,"refX":374,"refY":557,"markerWidth":558,"markerHeight":558,"orient":559},"sblStepArrow","0 0 10 10","5","7","auto-start-reverse",[79,561],{"d":562,"fill":159},"M0 0 L10 5 L0 10 z",[61,564,566],{"x":63,"y":565,"style":65,"fill":66,"textAnchor":67},"26","Each METHOD narrows or widens what is selected",[54,568],{"x":71,"y":124,"width":569,"height":101,"rx":74,"fill":570,"stroke":83,"style":77},"200","#eff3ff",[61,572,575],{"x":573,"y":574,"style":96,"fill":83,"textAnchor":67},"124","84","by expression",[61,577,580],{"x":573,"y":578,"style":579,"fill":159,"textAnchor":67},"106","text-anchor:middle;font-size:9.5px;font-family:monospace","use = 'residential'",[61,582,585],{"x":573,"y":583,"style":584,"fill":66,"textAnchor":67},"146","text-anchor:middle;font-size:18px;font-weight:bold;font-family:sans-serif","12,400",[148,587],{"x1":588,"y1":589,"x2":590,"y2":589,"stroke":159,"style":591},"224","116","272","stroke-width:1.8;marker-end:url(#sblStepArrow)",[54,593],{"x":594,"y":124,"width":569,"height":101,"rx":74,"fill":595,"stroke":116,"style":77},"280","#eef7f4",[61,597,598],{"x":63,"y":574,"style":96,"fill":116,"textAnchor":67},"METHOD 2",[61,600,602],{"x":63,"y":578,"style":601,"fill":159,"textAnchor":67},"text-anchor:middle;font-size:9.5px;font-family:sans-serif","within current: in flood zone",[61,604,605],{"x":63,"y":583,"style":584,"fill":66,"textAnchor":67},"1,130",[148,607],{"x1":608,"y1":589,"x2":609,"y2":589,"stroke":159,"style":591},"480","528",[54,611],{"x":612,"y":124,"width":569,"height":101,"rx":74,"fill":613,"stroke":104,"style":77},"536","#fdf2e2",[61,615,617],{"x":616,"y":574,"style":96,"fill":104,"textAnchor":67},"636","METHOD 3",[61,619,620],{"x":616,"y":578,"style":601,"fill":159,"textAnchor":67},"remove: behind defences",[61,622,623],{"x":616,"y":583,"style":584,"fill":91,"textAnchor":67},"920",[54,625],{"x":101,"y":569,"width":626,"height":90,"rx":374,"fill":75,"stroke":76,"style":627},"520","stroke-width:1.8",[61,629,631],{"x":63,"y":630,"style":158,"fill":159,"textAnchor":67},"223","METHOD 0 new · 1 add · 2 select within current · 3 remove from current",[231,633,635],{"className":233,"code":634,"language":235,"meta":236,"style":236},"from qgis.core import QgsProcessingFeatureSourceDefinition\n\nbuildings.selectByExpression(\"\\\"use\\\" = 'residential'\")\n\nprocessing.run(\"native:selectbylocation\", {\n    \"INPUT\": buildings, \"PREDICATE\": [INTERSECT],\n    \"INTERSECT\": flood, \"METHOD\": WITHIN_CURRENT,\n})\n\ndefences = QgsProject.instance().mapLayersByName(\"flood_defences\")[0]\ndefences.selectByExpression(\"\\\"condition\\\" IN ('good', 'fair')\")\nprotected = processing.run(\"native:buffer\", {\n    \"INPUT\": QgsProcessingFeatureSourceDefinition(defences.id(), selectedFeaturesOnly=True),\n    \"DISTANCE\": 20, \"DISSOLVE\": True, \"OUTPUT\": \"TEMPORARY_OUTPUT\",\n})[\"OUTPUT\"]\n\nprocessing.run(\"native:selectbylocation\", {\n    \"INPUT\": buildings, \"PREDICATE\": [INTERSECT],\n    \"INTERSECT\": protected, \"METHOD\": REMOVE,\n})\nprint(buildings.selectedFeatureCount(), \"residential buildings at risk and unprotected\")\n",[23,636,637,648,652,673,677,685,701,717,721,725,743,762,777,796,827,836,840,849,864,880,885],{"__ignoreMap":236},[240,638,639,641,643,645],{"class":148,"line":242},[240,640,256],{"class":245},[240,642,259],{"class":249},[240,644,246],{"class":245},[240,646,647],{"class":249}," QgsProcessingFeatureSourceDefinition\n",[240,649,650],{"class":148,"line":253},[240,651,271],{"emptyLinePlaceholder":270},[240,653,654,657,660,663,666,668,671],{"class":148,"line":267},[240,655,656],{"class":249},"buildings.selectByExpression(",[240,658,659],{"class":286},"\"",[240,661,662],{"class":293},"\\\"",[240,664,665],{"class":286},"use",[240,667,662],{"class":293},[240,669,670],{"class":286}," = 'residential'\"",[240,672,377],{"class":249},[240,674,675],{"class":148,"line":274},[240,676,271],{"emptyLinePlaceholder":270},[240,678,679,681,683],{"class":148,"line":299},[240,680,419],{"class":249},[240,682,422],{"class":286},[240,684,425],{"class":249},[240,686,687,689,692,695,697,699],{"class":148,"line":318},[240,688,431],{"class":286},[240,690,691],{"class":249},": buildings, ",[240,693,694],{"class":286},"\"PREDICATE\"",[240,696,443],{"class":249},[240,698,326],{"class":293},[240,700,448],{"class":249},[240,702,703,705,708,711,713,715],{"class":148,"line":323},[240,704,454],{"class":286},[240,706,707],{"class":249},": flood, ",[240,709,710],{"class":286},"\"METHOD\"",[240,712,466],{"class":249},[240,714,393],{"class":293},[240,716,471],{"class":249},[240,718,719],{"class":148,"line":380},[240,720,477],{"class":249},[240,722,723],{"class":148,"line":411},[240,724,271],{"emptyLinePlaceholder":270},[240,726,727,730,732,734,737,739,741],{"class":148,"line":416},[240,728,729],{"class":249},"defences ",[240,731,280],{"class":245},[240,733,283],{"class":249},[240,735,736],{"class":286},"\"flood_defences\"",[240,738,290],{"class":249},[240,740,56],{"class":293},[240,742,296],{"class":249},[240,744,745,748,750,752,755,757,760],{"class":148,"line":428},[240,746,747],{"class":249},"defences.selectByExpression(",[240,749,659],{"class":286},[240,751,662],{"class":293},[240,753,754],{"class":286},"condition",[240,756,662],{"class":293},[240,758,759],{"class":286}," IN ('good', 'fair')\"",[240,761,377],{"class":249},[240,763,764,767,769,772,775],{"class":148,"line":437},[240,765,766],{"class":249},"protected ",[240,768,280],{"class":245},[240,770,771],{"class":249}," processing.run(",[240,773,774],{"class":286},"\"native:buffer\"",[240,776,425],{"class":249},[240,778,779,781,784,788,790,793],{"class":148,"line":451},[240,780,431],{"class":286},[240,782,783],{"class":249},": QgsProcessingFeatureSourceDefinition(defences.id(), ",[240,785,787],{"class":786},"s9osk","selectedFeaturesOnly",[240,789,280],{"class":245},[240,791,792],{"class":293},"True",[240,794,795],{"class":249},"),\n",[240,797,798,801,803,806,808,811,813,815,817,820,822,825],{"class":148,"line":460},[240,799,800],{"class":286},"    \"DISTANCE\"",[240,802,466],{"class":249},[240,804,805],{"class":293},"20",[240,807,329],{"class":249},[240,809,810],{"class":286},"\"DISSOLVE\"",[240,812,466],{"class":249},[240,814,792],{"class":293},[240,816,329],{"class":249},[240,818,819],{"class":286},"\"OUTPUT\"",[240,821,466],{"class":249},[240,823,824],{"class":286},"\"TEMPORARY_OUTPUT\"",[240,826,471],{"class":249},[240,828,829,832,834],{"class":148,"line":474},[240,830,831],{"class":249},"})[",[240,833,819],{"class":286},[240,835,296],{"class":249},[240,837,838],{"class":148,"line":480},[240,839,271],{"emptyLinePlaceholder":270},[240,841,843,845,847],{"class":148,"line":842},17,[240,844,419],{"class":249},[240,846,422],{"class":286},[240,848,425],{"class":249},[240,850,852,854,856,858,860,862],{"class":148,"line":851},18,[240,853,431],{"class":286},[240,855,691],{"class":249},[240,857,694],{"class":286},[240,859,443],{"class":249},[240,861,326],{"class":293},[240,863,448],{"class":249},[240,865,867,869,872,874,876,878],{"class":148,"line":866},19,[240,868,454],{"class":286},[240,870,871],{"class":249},": protected, ",[240,873,710],{"class":286},[240,875,466],{"class":249},[240,877,398],{"class":293},[240,879,471],{"class":249},[240,881,883],{"class":148,"line":882},20,[240,884,477],{"class":249},[240,886,888,890,892,895],{"class":148,"line":887},21,[240,889,483],{"class":293},[240,891,486],{"class":249},[240,893,894],{"class":286},"\"residential buildings at risk and unprotected\"",[240,896,377],{"class":249},[14,898,899,497,901,903,904,907,908,910,911,907,914,917,918,921],{},[205,900,496],{},[23,902,393],{}," keeps only already-selected features that also meet the predicate — the spatial equivalent of ",[23,905,906],{},"AND",". ",[23,909,398],{}," deselects matches — ",[23,912,913],{},"AND NOT",[23,915,916],{},"QgsProcessingFeatureSourceDefinition"," with ",[23,919,920],{},"selectedFeaturesOnly=True"," makes any algorithm use just the selected features of a layer, here only defences in good or fair condition. Dissolving the buffer produces one polygon rather than hundreds of overlapping ones, which makes the final location test faster. The chain reads like the question it answers, which is a real advantage when someone has to check the method later.",[14,923,924,925,928],{},"Two cautions apply to chained selections. First, every step changes state on a shared layer, so a script that is interrupted half-way leaves a partial selection behind that looks like a finished answer; clear the selection with ",[23,926,927],{},"removeSelection()"," at the start of the script, not only at the end. Second, a selection made in the Python console is visible to the user immediately and will be used by any tool they run next with \"selected features only\" ticked — convenient in an interactive session, surprising in a plugin that runs in the background. Plugins should usually extract to a temporary layer rather than borrow the user's selection.",[194,930,932],{"id":931},"extract-matching-features-to-a-new-layer","Extract matching features to a new layer",[14,934,935,936,939],{},"When the result should be a layer rather than a selection — to hand to someone, to feed another algorithm, or simply because selections are lost when the project closes — use ",[23,937,938],{},"native:extractbylocation"," with the same parameters and an output.",[231,941,943],{"className":233,"code":942,"language":235,"meta":236,"style":236},"at_risk = processing.run(\"native:extractbylocation\", {\n    \"INPUT\": QgsProcessingFeatureSourceDefinition(buildings.id(), selectedFeaturesOnly=True),\n    \"PREDICATE\": [INTERSECT],\n    \"INTERSECT\": flood,\n    \"OUTPUT\": \"\u002Fdata\u002Fwork\u002Fbuildings_at_risk.gpkg\",\n})[\"OUTPUT\"]\n\nwells = QgsProject.instance().mapLayersByName(\"private_wells\")[0]\nprotected_areas = QgsProject.instance().mapLayersByName(\"source_protection_zones\")[0]\nunprotected = processing.run(\"native:extractbylocation\", {\n    \"INPUT\": wells, \"PREDICATE\": [DISJOINT],\n    \"INTERSECT\": protected_areas, \"OUTPUT\": \"TEMPORARY_OUTPUT\",\n})[\"OUTPUT\"]\nprint(unprotected.featureCount(), \"wells outside every protection zone\")\n",[23,944,945,959,974,984,990,1002,1010,1014,1032,1050,1063,1078,1093,1101],{"__ignoreMap":236},[240,946,947,950,952,954,957],{"class":148,"line":242},[240,948,949],{"class":249},"at_risk ",[240,951,280],{"class":245},[240,953,771],{"class":249},[240,955,956],{"class":286},"\"native:extractbylocation\"",[240,958,425],{"class":249},[240,960,961,963,966,968,970,972],{"class":148,"line":253},[240,962,431],{"class":286},[240,964,965],{"class":249},": QgsProcessingFeatureSourceDefinition(buildings.id(), ",[240,967,787],{"class":786},[240,969,280],{"class":245},[240,971,792],{"class":293},[240,973,795],{"class":249},[240,975,976,978,980,982],{"class":148,"line":267},[240,977,440],{"class":286},[240,979,443],{"class":249},[240,981,326],{"class":293},[240,983,448],{"class":249},[240,985,986,988],{"class":148,"line":274},[240,987,454],{"class":286},[240,989,457],{"class":249},[240,991,992,995,997,1000],{"class":148,"line":299},[240,993,994],{"class":286},"    \"OUTPUT\"",[240,996,466],{"class":249},[240,998,999],{"class":286},"\"\u002Fdata\u002Fwork\u002Fbuildings_at_risk.gpkg\"",[240,1001,471],{"class":249},[240,1003,1004,1006,1008],{"class":148,"line":318},[240,1005,831],{"class":249},[240,1007,819],{"class":286},[240,1009,296],{"class":249},[240,1011,1012],{"class":148,"line":323},[240,1013,271],{"emptyLinePlaceholder":270},[240,1015,1016,1019,1021,1023,1026,1028,1030],{"class":148,"line":380},[240,1017,1018],{"class":249},"wells ",[240,1020,280],{"class":245},[240,1022,283],{"class":249},[240,1024,1025],{"class":286},"\"private_wells\"",[240,1027,290],{"class":249},[240,1029,56],{"class":293},[240,1031,296],{"class":249},[240,1033,1034,1037,1039,1041,1044,1046,1048],{"class":148,"line":411},[240,1035,1036],{"class":249},"protected_areas ",[240,1038,280],{"class":245},[240,1040,283],{"class":249},[240,1042,1043],{"class":286},"\"source_protection_zones\"",[240,1045,290],{"class":249},[240,1047,56],{"class":293},[240,1049,296],{"class":249},[240,1051,1052,1055,1057,1059,1061],{"class":148,"line":416},[240,1053,1054],{"class":249},"unprotected ",[240,1056,280],{"class":245},[240,1058,771],{"class":249},[240,1060,956],{"class":286},[240,1062,425],{"class":249},[240,1064,1065,1067,1070,1072,1074,1076],{"class":148,"line":428},[240,1066,431],{"class":286},[240,1068,1069],{"class":249},": wells, ",[240,1071,694],{"class":286},[240,1073,443],{"class":249},[240,1075,337],{"class":293},[240,1077,448],{"class":249},[240,1079,1080,1082,1085,1087,1089,1091],{"class":148,"line":437},[240,1081,454],{"class":286},[240,1083,1084],{"class":249},": protected_areas, ",[240,1086,819],{"class":286},[240,1088,466],{"class":249},[240,1090,824],{"class":286},[240,1092,471],{"class":249},[240,1094,1095,1097,1099],{"class":148,"line":451},[240,1096,831],{"class":249},[240,1098,819],{"class":286},[240,1100,296],{"class":249},[240,1102,1103,1105,1108,1111],{"class":148,"line":460},[240,1104,483],{"class":293},[240,1106,1107],{"class":249},"(unprotected.featureCount(), ",[240,1109,1110],{"class":286},"\"wells outside every protection zone\"",[240,1112,377],{"class":249},[14,1114,1115,1117,1118,1121,1122,1124,1125,1127],{},[205,1116,496],{}," Feeding the selection into ",[23,1119,1120],{},"extractbylocation"," via the source definition keeps the attribute and spatial steps from the previous section. ",[23,1123,337],{}," answers \"not within any\" correctly because it tests against the comparison layer as a whole: a well is extracted only if it touches none of the zones. Running ",[23,1126,357],{}," and then inverting the selection gives the same answer on points but not on lines or polygons, where features that straddle a boundary are neither within nor disjoint — a subtle difference worth being deliberate about.",[14,1129,1130],{},[39,1131,1134,1137,1140,1143,1146,1151,1157,1160,1164,1167,1170,1175,1178,1181,1184,1187,1190,1193],{"viewBox":1132,"role":42,"ariaLabel":1133,"xmlns":44},"0 0 760 236","Disjoint versus inverted within for polygons: a feature straddling the boundary is not within and not disjoint, so inverting a within selection includes it while a disjoint selection excludes it",[46,1135,1136],{},"“Not within” is not “disjoint”",[50,1138,1139],{},"A zone with three parcels: one inside, one straddling, one outside. Selecting within and inverting gives the straddling and outside parcels. Selecting disjoint gives only the outside parcel. The straddling parcel is the difference, and whether it counts as outside depends on the question.",[54,1141],{"x":56,"y":56,"width":57,"height":1142,"fill":59},"236",[61,1144,1145],{"x":63,"y":565,"style":65,"fill":66,"textAnchor":67},"The straddling feature decides which you need",[54,1147],{"x":71,"y":1148,"width":1149,"height":1150,"rx":74,"fill":75,"stroke":104,"style":84},"44","344","172",[61,1152,1156],{"x":1153,"y":1154,"style":1155,"fill":104,"textAnchor":67},"196","68","text-anchor:middle;font-size:11.5px;font-weight:bold;font-family:sans-serif","within, then invert",[79,1158],{"d":1159,"fill":82,"stroke":83,"style":77},"M60 86 L230 86 L230 196 L60 196 z",[54,1161],{"x":574,"y":1162,"width":1148,"height":103,"fill":1163},"118","#c9c2ac",[79,1165],{"d":1166,"fill":104},"M204 112 L258 112 L258 158 L204 158 z",[54,1168],{"x":1169,"y":101,"width":114,"height":103,"fill":104},"290",[61,1171,1174],{"x":1153,"y":1172,"style":1173,"fill":159,"textAnchor":67},"210","text-anchor:middle;font-size:10px;font-family:sans-serif","selects straddling + outside",[54,1176],{"x":1177,"y":1148,"width":1149,"height":1150,"rx":74,"fill":75,"stroke":91,"style":84},"392",[61,1179,187],{"x":1180,"y":1154,"style":1155,"fill":91,"textAnchor":67},"564",[79,1182],{"d":1183,"fill":82,"stroke":83,"style":77},"M428 86 L598 86 L598 196 L428 196 z",[54,1185],{"x":1186,"y":1162,"width":1148,"height":103,"fill":1163},"452",[79,1188],{"d":1189,"fill":1163},"M572 112 L626 112 L626 158 L572 158 z",[54,1191],{"x":1192,"y":101,"width":114,"height":103,"fill":91},"658",[61,1194,1195],{"x":1180,"y":1172,"style":1173,"fill":159,"textAnchor":67},"selects outside only",[194,1197,1199],{"id":1198},"select-by-location-in-python","Select by location in Python",[14,1201,1202],{},"The algorithms are the right default. Dropping to the geometry API makes sense when the selection is one step in a loop, when the test needs a tolerance, or when you want per-feature detail such as how much of each building lies in the zone.",[231,1204,1206],{"className":233,"code":1205,"language":235,"meta":236,"style":236},"from qgis.core import (\n    QgsSpatialIndex, QgsFeatureRequest, QgsCoordinateTransform, QgsGeometry,\n)\n\ntransform = QgsCoordinateTransform(flood.crs(), buildings.crs(), QgsProject.instance())\nzones = []\nfor z in flood.getFeatures():\n    g = z.geometry()\n    g.transform(transform)\n    zones.append(g)\nzone = QgsGeometry.unaryUnion(zones)\nengine = QgsGeometry.createGeometryEngine(zone.constGet())\nengine.prepareGeometry()\n\nindex = QgsSpatialIndex(buildings.getFeatures(QgsFeatureRequest().setNoAttributes()))\ncandidates = index.intersects(zone.boundingBox())\n\nselected, share = [], {}\nfor f in buildings.getFeatures(QgsFeatureRequest().setFilterFids(candidates)):\n    g = f.geometry()\n    if engine.intersects(g.constGet()):\n        selected.append(f.id())\n        share[f.id()] = g.intersection(zone).area() \u002F g.area() if g.area() else 0\n\nbuildings.selectByIds(selected)\nmostly_in = [fid for fid, s in share.items() if s >= 0.5]\nprint(len(selected), \"intersect;\", len(mostly_in), \"have at least half their footprint in the zone\")\n",[23,1207,1208,1219,1224,1228,1232,1242,1252,1266,1276,1281,1286,1296,1306,1311,1315,1325,1335,1339,1349,1361,1370,1378,1384,1412,1417,1423,1457],{"__ignoreMap":236},[240,1209,1210,1212,1214,1216],{"class":148,"line":242},[240,1211,256],{"class":245},[240,1213,259],{"class":249},[240,1215,246],{"class":245},[240,1217,1218],{"class":249}," (\n",[240,1220,1221],{"class":148,"line":253},[240,1222,1223],{"class":249},"    QgsSpatialIndex, QgsFeatureRequest, QgsCoordinateTransform, QgsGeometry,\n",[240,1225,1226],{"class":148,"line":267},[240,1227,377],{"class":249},[240,1229,1230],{"class":148,"line":274},[240,1231,271],{"emptyLinePlaceholder":270},[240,1233,1234,1237,1239],{"class":148,"line":299},[240,1235,1236],{"class":249},"transform ",[240,1238,280],{"class":245},[240,1240,1241],{"class":249}," QgsCoordinateTransform(flood.crs(), buildings.crs(), QgsProject.instance())\n",[240,1243,1244,1247,1249],{"class":148,"line":318},[240,1245,1246],{"class":249},"zones ",[240,1248,280],{"class":245},[240,1250,1251],{"class":249}," []\n",[240,1253,1254,1257,1260,1263],{"class":148,"line":323},[240,1255,1256],{"class":245},"for",[240,1258,1259],{"class":249}," z ",[240,1261,1262],{"class":245},"in",[240,1264,1265],{"class":249}," flood.getFeatures():\n",[240,1267,1268,1271,1273],{"class":148,"line":380},[240,1269,1270],{"class":249},"    g ",[240,1272,280],{"class":245},[240,1274,1275],{"class":249}," z.geometry()\n",[240,1277,1278],{"class":148,"line":411},[240,1279,1280],{"class":249},"    g.transform(transform)\n",[240,1282,1283],{"class":148,"line":416},[240,1284,1285],{"class":249},"    zones.append(g)\n",[240,1287,1288,1291,1293],{"class":148,"line":428},[240,1289,1290],{"class":249},"zone ",[240,1292,280],{"class":245},[240,1294,1295],{"class":249}," QgsGeometry.unaryUnion(zones)\n",[240,1297,1298,1301,1303],{"class":148,"line":437},[240,1299,1300],{"class":249},"engine ",[240,1302,280],{"class":245},[240,1304,1305],{"class":249}," QgsGeometry.createGeometryEngine(zone.constGet())\n",[240,1307,1308],{"class":148,"line":451},[240,1309,1310],{"class":249},"engine.prepareGeometry()\n",[240,1312,1313],{"class":148,"line":460},[240,1314,271],{"emptyLinePlaceholder":270},[240,1316,1317,1320,1322],{"class":148,"line":474},[240,1318,1319],{"class":249},"index ",[240,1321,280],{"class":245},[240,1323,1324],{"class":249}," QgsSpatialIndex(buildings.getFeatures(QgsFeatureRequest().setNoAttributes()))\n",[240,1326,1327,1330,1332],{"class":148,"line":480},[240,1328,1329],{"class":249},"candidates ",[240,1331,280],{"class":245},[240,1333,1334],{"class":249}," index.intersects(zone.boundingBox())\n",[240,1336,1337],{"class":148,"line":842},[240,1338,271],{"emptyLinePlaceholder":270},[240,1340,1341,1344,1346],{"class":148,"line":851},[240,1342,1343],{"class":249},"selected, share ",[240,1345,280],{"class":245},[240,1347,1348],{"class":249}," [], {}\n",[240,1350,1351,1353,1356,1358],{"class":148,"line":866},[240,1352,1256],{"class":245},[240,1354,1355],{"class":249}," f ",[240,1357,1262],{"class":245},[240,1359,1360],{"class":249}," buildings.getFeatures(QgsFeatureRequest().setFilterFids(candidates)):\n",[240,1362,1363,1365,1367],{"class":148,"line":882},[240,1364,1270],{"class":249},[240,1366,280],{"class":245},[240,1368,1369],{"class":249}," f.geometry()\n",[240,1371,1372,1375],{"class":148,"line":887},[240,1373,1374],{"class":245},"    if",[240,1376,1377],{"class":249}," engine.intersects(g.constGet()):\n",[240,1379,1381],{"class":148,"line":1380},22,[240,1382,1383],{"class":249},"        selected.append(f.id())\n",[240,1385,1387,1390,1392,1395,1398,1401,1404,1406,1409],{"class":148,"line":1386},23,[240,1388,1389],{"class":249},"        share[f.id()] ",[240,1391,280],{"class":245},[240,1393,1394],{"class":249}," g.intersection(zone).area() ",[240,1396,1397],{"class":245},"\u002F",[240,1399,1400],{"class":249}," g.area() ",[240,1402,1403],{"class":245},"if",[240,1405,1400],{"class":249},[240,1407,1408],{"class":245},"else",[240,1410,1411],{"class":293}," 0\n",[240,1413,1415],{"class":148,"line":1414},24,[240,1416,271],{"emptyLinePlaceholder":270},[240,1418,1420],{"class":148,"line":1419},25,[240,1421,1422],{"class":249},"buildings.selectByIds(selected)\n",[240,1424,1426,1429,1431,1434,1436,1439,1441,1444,1446,1449,1452,1455],{"class":148,"line":1425},26,[240,1427,1428],{"class":249},"mostly_in ",[240,1430,280],{"class":245},[240,1432,1433],{"class":249}," [fid ",[240,1435,1256],{"class":245},[240,1437,1438],{"class":249}," fid, s ",[240,1440,1262],{"class":245},[240,1442,1443],{"class":249}," share.items() ",[240,1445,1403],{"class":245},[240,1447,1448],{"class":249}," s ",[240,1450,1451],{"class":245},">=",[240,1453,1454],{"class":293}," 0.5",[240,1456,296],{"class":249},[240,1458,1460,1462,1464,1467,1470,1473,1475,1477,1480,1483],{"class":148,"line":1459},27,[240,1461,483],{"class":293},[240,1463,371],{"class":249},[240,1465,1466],{"class":293},"len",[240,1468,1469],{"class":249},"(selected), ",[240,1471,1472],{"class":286},"\"intersect;\"",[240,1474,329],{"class":249},[240,1476,1466],{"class":293},[240,1478,1479],{"class":249},"(mostly_in), ",[240,1481,1482],{"class":286},"\"have at least half their footprint in the zone\"",[240,1484,377],{"class":249},[14,1486,1487,1489,1490,1493,1494,1497,1498,523,1502,219],{},[205,1488,496],{}," The zone is reprojected into the buildings' CRS and unioned into one geometry so each building is tested once rather than against every zone polygon. A prepared geometry engine makes repeated ",[23,1491,1492],{},"intersects"," tests against the same large polygon much faster. The spatial index narrows candidates to buildings whose bounding boxes overlap the zone's, and ",[23,1495,1496],{},"setFilterFids"," fetches only those. Computing the share of each footprint inside the zone answers a question neither algorithm can: a building clipped by a sliver of the zone is technically intersecting and practically not at risk. The pattern follows ",[31,1499,1501],{"href":1500},"\u002Fspatial-data-processing-automation\u002Fgeometry-operations-and-predicates\u002Fbuild-spatial-index-pyqgis\u002F","building and using a spatial index",[31,1503,1505],{"href":1504},"\u002Fspatial-data-processing-automation\u002Fgeometry-operations-and-predicates\u002Fcheck-geometry-intersects-pyqgis\u002F","testing whether geometries intersect",[194,1507,1509],{"id":1508},"qgis-version-compatibility","QGIS version compatibility",[14,1511,1512,523,1514,1516,1517,1520,1521,917,1523,1525],{},[23,1513,228],{},[23,1515,938],{}," replaced the ",[23,1518,1519],{},"qgis:"," versions in QGIS 3.12, with the same predicate codes. The predicate order has not changed through 3.44 or on the QGIS 4 series, but constants such as those defined above make a script robust if it ever does. ",[23,1522,916],{},[23,1524,787],{}," has been available since 3.0.",[194,1527,1529],{"id":1528},"troubleshooting","Troubleshooting",[199,1531,1532,1538,1552,1558,1564],{},[202,1533,1534,1537],{},[205,1535,1536],{},"Nothing is selected."," Invalid geometries in the comparison layer, or the layers have no real overlap because one has a wrong CRS assigned.",[202,1539,1540,497,1543,1545,1546,1548,1549,1551],{},[205,1541,1542],{},"Too much is selected.",[23,1544,326],{}," includes features that only touch the boundary; use ",[23,1547,357],{}," or ",[23,1550,352],{}," as appropriate.",[202,1553,1554,1557],{},[205,1555,1556],{},"The selection disappears."," Selections are not saved with data; extract to a layer if the result must persist.",[202,1559,1560,1563],{},[205,1561,1562],{},"Very slow on large polygon layers."," Dissolve or simplify the comparison layer first.",[202,1565,1566,1569],{},[205,1567,1568],{},"Different counts from the Python version."," Different handling of boundary contact; compare predicates, not code paths.",[194,1571,1573],{"id":1572},"conclusion","Conclusion",[14,1575,1576,1577,1579,1580,1582],{},"Use ",[23,1578,228],{}," to shape a selection and ",[23,1581,938],{}," to write one out, naming predicate and method codes as constants so the call reads as a sentence. Combine methods to build complex selections step by step, be deliberate about disjoint versus inverted within, and move to prepared geometries and a spatial index when you need tolerances or per-feature measurements.",[194,1584,1586],{"id":1585},"frequently-asked-questions","Frequently Asked Questions",[14,1588,1589,1592,1593,1596],{},[205,1590,1591],{},"Can I select features within a distance of another layer?","\nBuffer the comparison layer first and select by intersection, or use ",[23,1594,1595],{},"native:selectwithindistance"," where your version provides it.",[14,1598,1599,1602],{},[205,1600,1601],{},"Does selection by location work across CRSs?","\nYes; the comparison layer is reprojected on the fly. Check that both CRSs are correctly assigned.",[14,1604,1605,1608,1609,1612],{},[205,1606,1607],{},"How do I count matches per polygon instead of selecting?","\nUse ",[23,1610,1611],{},"native:countpointsinpolygon"," for points, or a spatial join with summary for other geometries.",[14,1614,1615,1618,1619,1622],{},[205,1616,1617],{},"Can the same layer be input and comparison?","\nYes, for questions like \"which parcels touch another parcel\", though every feature matches itself for most predicates. Exclude self-matches by comparing feature ids in the Python route, or by using ",[23,1620,1621],{},"native:joinattributesbylocation"," and filtering out rows where the joined id equals the feature's own.",[14,1624,1625,1628,1629,1632],{},[205,1626,1627],{},"How do I save the selection so it survives closing the project?","\nSelections are session state. Store the selected ids in a field — set a ",[23,1630,1631],{},"flag"," column to 1 for selected features inside an edit session — or extract the selection to its own layer. For recurring selections, a saved expression or a map theme with a filtered layer is often cleaner than persisting ids that change when data is reloaded.",[194,1634,1636],{"id":1635},"related","Related",[199,1638,1639,1644,1650,1656,1662],{},[202,1640,1641,1643],{},[31,1642,34],{"href":33}," — the guide this recipe belongs to",[202,1645,1646],{},[31,1647,1649],{"href":1648},"\u002Fpyqgis-fundamentals-environment-setup\u002Fworking-with-qgis-expressions\u002Fselect-features-by-expression-pyqgis\u002F","Select Features by Expression in PyQGIS",[202,1651,1652],{},[31,1653,1655],{"href":1654},"\u002Fspatial-data-processing-automation\u002Fvector-data-manipulation\u002Fspatial-join-points-in-polygons-pyqgis\u002F","Spatial Join Points to Polygons in PyQGIS",[202,1657,1658],{},[31,1659,1661],{"href":1660},"\u002Fspatial-data-processing-automation\u002Fvector-data-manipulation\u002Fcreate-hexagon-grid-and-count-points-pyqgis\u002F","Create a Hexagon Grid and Count Points in PyQGIS",[202,1663,1664],{},[31,1665,1667],{"href":1666},"\u002Fspatial-data-processing-automation\u002Fvector-data-manipulation\u002Fclip-vector-layer-pyqgis\u002F","Clip a Vector Layer in PyQGIS",[1669,1670,1671],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}",{"title":236,"searchDepth":253,"depth":253,"links":1673},[1674,1675,1676,1677,1678,1679,1680,1681,1682,1683],{"id":196,"depth":253,"text":197},{"id":222,"depth":253,"text":223},{"id":529,"depth":253,"text":530},{"id":931,"depth":253,"text":932},{"id":1198,"depth":253,"text":1199},{"id":1508,"depth":253,"text":1509},{"id":1528,"depth":253,"text":1529},{"id":1572,"depth":253,"text":1573},{"id":1585,"depth":253,"text":1586},{"id":1635,"depth":253,"text":1636},"Select or extract features using their spatial relationship to another layer with native:selectbylocation and native:extractbylocation — choosing predicates, combining with existing selections, using only selected features as the filter, and doing it in Python for full control.","md",{"slug":1687,"type":1688,"breadcrumb":1689,"datePublished":1690,"dateModified":1690},"select-features-by-location-pyqgis","article","Select Features by Location","2026-09-17","\u002Fspatial-data-processing-automation\u002Fvector-data-manipulation\u002Fselect-features-by-location-pyqgis",{"title":5,"description":1684},"spatial-data-processing-automation\u002Fvector-data-manipulation\u002Fselect-features-by-location-pyqgis\u002Findex","0pObBnRWFc-zObkcYYeZvnu-n2JGasBbFYBjjHuNGF4",1789632908630]