Eight business questions, eight filters

Each story starts with a question asked in a technical department, a local authority or a consultancy, then translates it into FilterMate settings, step by step, on the complete BD TOPO of a French department. The screenshots show the whole QGIS window so you can compare with your own screen, and every result comes with its numbers.

0The playground

Every story uses the same file: the BD TOPO 3.5 of Haute-Garonne, exactly as the French mapping agency (IGN) distributes it for free on the Géoplateforme, in a single 2.9 GB GeoPackage with 53 layers. Nothing was clipped beforehand: FilterMate scopes the territory every time.

LayerFeatures in the departmentRole in the stories
batiment (buildings)1,173,829Main target: what is protected, what is served
troncon_de_route (road segments)383,112Source of road buffers, target of crossings
haie · zone_de_vegetation (hedges, vegetation)416,105 · 261,051Vegetation to clear
troncon_hydrographique · surface_hydrographique49,344 · 9,969Watercourses and water surfaces
erp (public buildings)11,384Schools, town halls, shops
construction_lineaire12,473Bridges, dams, walls
commune · epci930 · 38Scoping territories
The common thread. Every story follows the same three beats: scope the territory with a first filter (a commune or an EPCI as source layer, every other layer as target), ask the business question with a second filter whose source is an already scoped layer, then read the result in the Layers panel and on the map. The timings quoted come from filtermate.log on an ordinary laptop.
One rule to know. On GeoPackage, a new spatial filter applied to a target layer replaces that layer's previous spatial filter; the AND combine operator only applies to an existing attribute filter, or to the source layer. Stories 3 and 4 take advantage of it (the question deliberately spills over the commune boundary), story 6 works around it with an attribute scope.

1The commune dossier in three minutes

The need

Camille, a project officer in a consultancy, is answering a tender from the town of Saint-Gaudens. She has the complete department GeoPackage and must deliver tonight only what concerns the commune: buildings, roads, hydrography, vegetation, facilities. With styles, in a file the client opens with a double-click.

The FilterMate translation

The commune is the source layer, picked by name in single selection. Every other layer is ticked at once in Layers to filter, with the Intersect predicate and no buffer. The Exporting tab then writes a GeoPackage with embedded project, QML styles and a ZIP archive.

  1. Load the 13 layers and open FilterMate. The Layers panel shows the counts of the whole department: 1,173,829 buildings, 383,112 road segments. Click commune: it becomes the source layer. In the Exploring area, tick Single selection, set the display expression to "nom_officiel" and type "Saint-Gaudens" in the list. The Tracking button of the Exploring column being on, the canvas recentres on the commune by itself.
    Step 1: the commune of Saint-Gaudens is picked in single selection, the canvas has recentred on it, the Layers panel shows department-wide counts
    Step 1. The commune is selected (yellow highlight); around it the whole department is still loaded.
  2. Tick every target. Filtering tab, Layers to filter row: right-click in the list, then Select All. The Intersect predicate is ticked, the Buffer row stays off.
    Step 2: the Layers to filter row lists the 12 target layers, Intersect is ticked
    Step 2. Twelve target layers, one predicate, no buffer.
  3. Filter. The log reports under a second for the twelve layers: on GeoPackage, FilterMate first queries the R-tree index of each table, then evaluates ST_Intersects on the candidates only.
    Step 3: only the features touching the commune remain on the twelve layers
    Step 3. The layers only show the commune's content. Vegetation polygons straddling the boundary are kept whole: that is what Intersect means.
    Step 3b: zoom on the centre of Saint-Gaudens, buildings in red, public buildings in yellow, roads in black
    Zoom on the town centre: 12,380 buildings, 317 public buildings, 2,902 road segments.
  4. Configure the export. Exporting tab: the 12 layers, EPSG:2154, styles as QML, GPKG format, output folder and a ZIP archive.
    Step 4: the Exporting tab is configured with the 12 layers, QML, GPKG, folder and ZIP
    Step 4. Everything is set, nothing is written yet.
  5. Export. Because the format is GeoPackage and several layers are exported, FilterMate shows a recap and offers to keep the group hierarchy. Confirm: the file is written in 4 seconds with an embedded QGIS project.
    GeoPackage export recap dialog listing the layers and the keep-groups option
    The recap before writing.
    Step 5: the message bar confirms the export, the map is unchanged
    Step 5. Export done; the client will open the .gpkg and find the map as is.

Result

LayerDepartmentSaint-Gaudens
batiment1,173,82912,380
troncon_de_route383,1122,902
haie416,1051,505
zone_de_vegetation261,0511,006
erp11,384317
troncon_hydrographique49,344157
zone_d_habitation31,669109
construction_lineaire12,47377
surface_hydrographique9,96942
equipement_de_transport4,25539
terrain_de_sport2,97327
cimetiere1,1422

Under the hood

Provider filter generated for the buildings layer, as read in Layer Properties → Source:

ROWID IN (SELECT id FROM "rtree_batiment_geometrie"
          WHERE minx <= 517706.0 AND maxx >= 511938.3
            AND miny <= 6231762.5 AND maxy >= 6222765.8)
AND ST_Intersects("geometrie", ST_MakeValid(ST_GeomFromText('Polygon ((…))', 2154)))
Going further. If polygons straddling the boundary get in the way, replace Intersect with Are within: only objects entirely inside the commune remain. On very detailed polygons, the centroid box to the right of the Layers to filter row speeds up the cascade further.

2Who lives next to the main roads?

The need

Nadia is writing the noise chapter of the local plan of Muret, crossed by the A64 motorway and several departmental roads. The noise classification of infrastructures imposes sector widths that depend on the road category. She wants the list of buildings and public buildings located in those sectors, with a width that depends on each road.

The FilterMate translation

After scoping on Muret, the source layer becomes troncon_de_route with the custom selection "importance" IN ('1', '2'). The buffer is an expression evaluated for each segment: 300 m for importance 1, 250 m for importance 2. The Flat buffer type avoids round ends at segment tips. Targets: batiment and erp.

  1. Scope Muret. Same gesture as in story 1: commune as source, Muret in single selection, every layer as target, Intersect, Filter. Muret has 19,458 buildings, 354 public buildings and 5,512 road segments.
    Step 1: Muret scoped, buildings, public buildings, roads and railway limited to the commune
    Step 1. The commune is scoped; the A64 crosses it from north-east to south-west.
  2. Pick the main roads. Click troncon_de_route in the Layers panel: it becomes the source. Tick Custom selection and type "importance" IN ('1', '2'). 102 segments are kept out of the commune's 5,512.
    Step 2: the custom expression keeps the 102 segments of importance 1 and 2, highlighted in yellow
    Step 2. The motorway and the main departmental roads are highlighted.
  3. Buffer by expression. Targets batiment and erp, Intersect predicate. On the Buffer value row, click the small arrow left of the field to switch to expression mode and type:
    CASE WHEN "importance" = '1' THEN 300
         WHEN "importance" = '2' THEN 250
         ELSE 100 END
    On the next row, choose the Flat type.
    Step 3: the Buffer value row is in expression mode, the buffer type is Flat
    Step 3. The distance is no longer a number but a QGIS expression evaluated segment by segment.
  4. Filter.
    Step 4: only the buildings and public buildings inside the noise sectors remain
    Step 4. Buildings and public buildings outside the sectors have left the map.
    Step 4b: zoom on the A64, the 300 m band shows in the distribution of buildings
    Zoom: the 300 m band around the A64 shows in the distribution of the remaining buildings.

Result

1,999 buildings and 74 public buildings of Muret lie in the noise sectors of the 102 segments of importance 1 and 2.

Going further. The same expression can read a regulatory width stored in an attribute, for instance "largeur_de_chaussee" * 3. Segments with an empty width need a coalesce("largeur_de_chaussee", 3).

3How far the Garonne can reach

The need

Julien prepares, for the planning department of Grenade, a meeting on the flood risk prevention plan. The commune sits at the confluence of the Garonne and the Save. He first wants to show everything within 300 m of the water surfaces, then tighten to 100 m for the frequent flood, and be able to step back in front of the councillors.

The FilterMate translation

Source: surface_hydrographique, scoped on Grenade, with a multiple selection and Select All (77 surfaces). Targets: buildings, public buildings and roads, Intersect predicate, 300 m buffer. A second Filter at 100 m, then Undo in the action bar.

  1. Scope Grenade. 6,998 buildings, 79 public buildings, 1,978 road segments and 77 water surfaces.
    Step 1: Grenade scoped, the Garonne and the Save in blue
    Step 1. The water surfaces (Garonne to the east, Save to the south) are now the only ones on the map.
  2. Select every water surface. Click surface_hydrographique, tick Multiple selection, then right-click in the list and Select All. The summary above the list counts 77 features.
    Step 2: the 77 water surfaces are ticked in the multiple selection
    Step 2. The list shows the nature and id of each surface; all are ticked.
  3. 300 m. Targets batiment, erp and troncon_de_route, Intersect, Buffer value 300. Filter.
    Step 3: buildings, public buildings and roads within 300 m of the water surfaces
    Step 3. The 300 m band follows the Garonne well beyond Grenade: the river polygons are long, and the targets' spatial filter replaces the commune scope.
  4. 100 m. Change the buffer value and press Filter again.
    Step 4: the band is tightened to 100 m
    Step 4. The result tightens onto the banks.
  5. Undo. The first button after Filter restores the previous state of the three layers, at 300 m. Redo would reapply it. The history belongs to the project and survives a QGIS restart.
    Step 5: Undo has restored the 300 m band
    Step 5. Back to 300 m in one click.

Result

BandBuildingsPublic buildingsRoad segments
300 m around Grenade's water surfaces14,1811686,243
100 m2,727271,934
Why more than the commune? Grenade has 6,998 buildings, the 300 m band holds 14,181: the Garonne polygons touching the commune stretch for tens of kilometres and the buffer follows them into the neighbours. To stay inside the commune, take troncon_hydrographique as source, whose segments are short, or export the commune first (story 1) and work on the resulting file.

4Every bridge in the metropolis

The need

Karim manages the engineering structures of Toulouse Métropole: 37 communes, close to 99,000 road segments. He wants the inventory of the places where roads cross a permanent watercourse, segments and structures, to plan inspections.

The FilterMate translation

Scoping is done this time on the epci layer. Then the source becomes troncon_hydrographique with the custom selection "persistance" = 'Permanent', the targets troncon_de_route and construction_lineaire, and the Cross predicate, without buffer: a road running along the river is not kept, a road crossing it is.

  1. Scope the EPCI. epci layer as source, "Toulouse Métropole" in single selection on "nom_officiel", every other layer as target, Intersect. The filter returns 98,687 road segments, 1,844 watercourse segments, 1,181 linear constructions and 70 touched communes.
    Step 1: Toulouse Métropole scoped, the Garonne crosses the metropolis from south to north
    Step 1. The whole metropolis, Garonne, Hers and Touch included.
  2. Keep only permanent watercourses. Source troncon_hydrographique, Custom selection "persistance" = 'Permanent': 691 segments.
    Step 2: the 691 permanent watercourse segments are highlighted
    Step 2. Ditches and intermittent flows do not count.
  3. Cross. Targets troncon_de_route and construction_lineaire, Cross predicate alone, Buffer row off. Filter.
    Step 3: the Cross predicate is the only one ticked, the Buffer row is off
    Step 3. One predicate, no buffer.
    Step 3b: only the road segments and structures crossing a watercourse remain
    Result at metropolis scale: the crossings draw the river network.
    Zoom on the north of Toulouse: bridges over the Garonne and the Hers
    Zoom on the north of Toulouse: every remaining segment is a bridge or a crossing.

Result

1,112 road segments and 190 linear constructions (mostly bridges) cross a permanent watercourse within the metropolis extent.

Why not Intersect? With Intersect and a buffer of a few metres, every road running along a bank would be kept as well. Cross only keeps what goes across. The Touch predicate would only keep segments ending exactly on the bank.

5Clearing brush around homes

The need

Élodie, at the town hall of Bagnères-de-Luchon, must inform the owners subject to the legal brush-clearing obligation: vegetation within 50 m of a dwelling. She wants the map of the woods and forests concerned, without the hedges, which fall under another regime.

The FilterMate translation

Source batiment with the custom selection "usage_1" = 'Résidentiel', targets zone_de_vegetation and haie, Intersect, 50 m buffer. Then a second, attribute filter on the vegetation layer turned source, combined with AND with the previous spatial filter.

  1. Scope Luchon. 3,699 buildings, 269 vegetation zones, 123 hedges.
    Step 1: Bagnères-de-Luchon scoped, vegetation in green, buildings in red
    Step 1. The inhabited valley and the wooded slopes.
  2. Keep only dwellings. Source batiment, Custom selection "usage_1" = 'Résidentiel': 1,619 buildings.
    Step 2: residential buildings are highlighted
    Step 2. Outbuildings, farm and industrial buildings are left out of the source.
  3. 50 m. Targets zone_de_vegetation and haie, Intersect, Buffer 50. Filter: 119 vegetation zones and 48 hedges remain.
    Step 3: vegetation within 50 m of a dwelling
    Step 3. Hedges and undifferentiated woods are still there.
  4. Keep only woods and forests. Click zone_de_vegetation in the Layers panel: it becomes the source. Custom selection:
    "nature" IN ('Bois', 'Forêt fermée de feuillus', 'Forêt fermée de conifères',
                 'Forêt fermée mixte', 'Forêt ouverte')
    Enable the Combine operator row and leave AND on the left: the new filter narrows the spatial filter already applied to the source layer instead of replacing it.
    Step 4: expression on the vegetation nature, AND combine operator enabled
    Step 4. The button of the Combine operator row is on, the left operator reads AND.
  5. Filter.
    Step 5: only woods and forests within 50 m of a dwelling remain
    Step 5. 58 woods and forests within 50 m of a dwelling.
    Zoom on the centre of Luchon and its wooded slopes
    Zoom: the edges to clear surround the hillside neighbourhoods.

Result

Out of the commune's 269 vegetation zones, 119 touch the 50 m band around a dwelling, among which 58 woods and forests; 48 hedges are in the same case.

Under the hood

The vegetation layer's filter after step 5 keeps the spatial clause and adds the attribute clause:

(ROWID IN (SELECT id FROM "rtree_zone_de_vegetation_geometrie" WHERE …)
 AND ST_Intersects("geometrie", ST_Buffer(ST_MakeValid(ST_GeomFromText('MultiPolygon (…)', 2154)), 50.0)))
AND ("nature" IN ('Bois', 'Forêt fermée de feuillus', 'Forêt fermée de conifères', 'Forêt fermée mixte', 'Forêt ouverte'))

6Hamlets the rescue services reach badly

The need

At the fire station of Aspet, in the Pyrenean foothills, the response plan is being prepared: which hamlets and activity zones lie more than 200 m from a paved road, hence reachable only by track or footpath?

The FilterMate translation

This is the Disjoint predicate with a 200 m buffer: keep what shares no point with the buffer zone. Since Disjoint keeps everything far away, including the rest of the department, the target layers are first scoped by an attribute filter on the INSEE code, applied with FilterMate's Processing algorithm. The second filter then combines with AND.

  1. Scope Aspet spatially for roads, buildings and vegetation (story 1), then by attribute for the two target layers: Toolbox → FilterMate → Filter multiple layers, layers zone_d_habitation and zone_d_activite_ou_d_interet, expression "insee_commune" = '31020'. 87 hamlets and 31 activity zones.
    Step 1: Aspet scoped, hamlets in orange
    Step 1. The two target layers carry an attribute filter, the others a spatial one.
  2. Keep only paved roads. Source troncon_de_route, Custom selection "nature" NOT IN ('Chemin', 'Sentier', 'Escalier', 'Piste cyclable', 'Route empierrée'): 494 segments out of 1,168.
    Step 2: paved roads are highlighted, tracks and footpaths are not
    Step 2. Tracks and footpaths, plentiful in the mountains, are left out.
  3. Disjoint, 200 m, AND. Targets zone_d_habitation and zone_d_activite_ou_d_interet, Disjoint predicate alone, Buffer 200, Combine operator row on with AND on the right (the target layers' operator).
    Step 3: Disjoint ticked, 200 m buffer, AND operator for the target layers
    Step 3. Disjoint plus buffer: an exclusion ring.
  4. Filter.
    Step 4: only the hamlets more than 200 m from a paved road remain
    Step 4. The remaining hamlets are those no paved road comes within 200 m of.

Result

22 hamlets of Aspet are more than 200 m from a paved road; none of the 31 activity zones is. At 100 m they would be 32.

Disjoint without scope. Without the attribute filter of step 1, Disjoint would have returned the 31,599 hamlets of the department that do not touch the 200 m band around Aspet's roads. An exclusion predicate always requires bounding the targets first.

7The team's query library

The need

Julien (story 3) will redo the 300 m band at every BD TOPO update and wants his colleagues to replay it without him. The filter must exist outside his head: named, described, reapplicable in one click, exportable.

The FilterMate translation

A favorite records the complete filter: source layer, selection, predicates, buffer, target layers. The menu opens from the ★ badge in the header; the manager lets you rename, describe, change the scope (this project or all projects) and export as JSON. With the sharing extension, a shared git repository becomes the team library.

  1. Save. The 300 m filter of story 3 is applied. Click the ★ badge then Add filter, name it "PPRI Garonne 300 m".
    Step 1: the message bar confirms that the PPRI Garonne 300 m favorite was added
    Step 1. The message bar confirms the save; the favorite immediately shows in the Quick filtering section of the ★ menu.
  2. Unfilter. The three layers get the whole department back: 1,173,829 buildings.
    Step 2: after Unfilter, every feature is back
    Step 2. Back to the unfiltered state.
  3. Replay. ★ badge then "PPRI Garonne 300 m": the filter reapplies, with the same 14,181 buildings, 168 public buildings and 6,243 segments.
    Step 3: the reapplied favorite gives exactly the result of story 3
    Step 3. Same result, one click.
  4. Describe and share. Manage favorites… opens the manager: description, tags, scope, exact expression, Remote tab to publish to a git repository. Export… writes a JSON file to send to a colleague, who imports it from the same menu.
    The favorites manager with the PPRI Garonne 300 m favorite selected
    Step 4. The manager: list on the left, details and expression on the right.
Scope. A project-scoped favorite is also saved in the .qgz file; a global favorite follows the user into every project. The manager's usage statistics show which ones are actually used.

8What changed since the last edition?

The need

Sophie administers the department's GIS and has just received the March 2026 edition of the BD TOPO. Before publishing it, she wants to isolate the objects modified since the previous edition on four layers, for a quality check, and be able to redo that check in a Processing model at every edition.

The FilterMate translation

No geometry here: a single attribute filter to apply to several layers. That is the job of the filtermate:batch_filter algorithm of the Processing toolbox, usable in the graphical modeler, in batch mode or from Python.

  1. Open the toolbox and search for "filtermate".
    Step 1: the Processing toolbox filtered on filtermate shows the Filter multiple layers algorithm
    Step 1. The FilterMate provider and its batch filter algorithm.
  2. Choose the layers and the expression. batiment, troncon_de_route, troncon_hydrographique, erp and the expression "date_modification" >= '2025-03-15'.
    The algorithm dialog with four layers and the expression on the modification date
    Step 2. An ordinary Processing dialog: it chains in a model like any other.
  3. Run. The four layers receive the filter in one pass.
    Step 3: around Toulouse, only objects modified since March 2025 remain
    Step 3. Around Toulouse, the objects modified in the last year.

Result

LayerDepartmentModified since 15 March 2025
troncon_de_route383,112173,616
troncon_hydrographique49,34428,519
batiment1,173,82922,954
erp11,3843

The same thing from the Python console

import processing
processing.run("filtermate:batch_filter", {
    "INPUT_LAYERS": ["batiment", "troncon_de_route", "troncon_hydrographique", "erp"],
    "EXPRESSION": "\"date_modification\" >= '2025-03-15'",
})

9Replaying these stories at home

  1. Download the BD TOPO of your department from the IGN Géoplateforme ("all themes", GeoPackage format, Lambert-93). The file ships with its spatial indexes: that is what makes the cascades fast.
  2. Load the layers named in each story. The styles embedded in the GeoPackage hide buildings beyond 1:25,000: disable scale-dependent visibility in the layer properties, or apply your own styles.
  3. Replace the commune names with yours. The fields used (nom_officiel, importance, persistance, usage_1, nature, insee_commune, date_modification) are those of BD TOPO 3.x, identical in every department.
  4. To reproduce the screenshots, the repository script scripts/recipe_screenshots.py drives QGIS from end to end of each story, checks the counts and saves one image per step.
Verification. Every count on this page was checked against an independent computation (GDAL/OGR, without FilterMate) on the same data. The differences found and their explanation are recorded in the repository.