2

Scenario: I have a line layer with a column where there are two different details about the condition (Road, Path). A second column (Parcel) defines in which parcel this condition is located. f.e.:

parcel condition
73463 road
73463 path
73464 road
73465 path
73465 path

Problem: I would like to create an atlas function in the layout that displays all roads and paths sorted by parcel that are located in the active parcel, if possible with a dynamic function in the legend text to describe the length of each line within the parcel.

3
  • Do you have a parcel layer that is being used as they Atlas layer? Or is the Atlas being controlled by the roads/paths layer? Mar 25 at 16:14
  • In this scenario Atlas should be controlled by the "roads/path" Layer, but a separate parcel layer exists, in case this would be a feasible approach.
    – Marek
    Mar 25 at 16:37
  • I had my answer mostly written before I saw your reply, see if that works :) Mar 25 at 16:48

2 Answers 2

7

For this answer I have a parcels layer with a numeric attribute "parcel_id", and a routes layers with a numeric attribute "parcel_id" for its parent parcel, and a text attribute "condition" with 'path' or 'road' attributes.

The parcels layer is controlling the Atlas, using the "parcel_id" attribute as the page name.

To only display routes that are within the current parcel feature you need to set up rule based symbology which filters using the routes' parcel_id attribute and matches it to the Atlas feature id, which used the parcel's parcel_id attribute:

"parcel_id" = @atlas_featureid

Combine that with rules for setting up the symbology classes and you get the following:

enter image description here

Now when you scroll through pages in the Atlas it will filter just to the features within that parcel.

To configure the legend to display some smarts, use the Expression setting:

enter image description here

Use an aggregate() function to sum the lengths of all the routes, but filter it by the "parcel_id" (using the Atlas feature id) and the "condition" (using the symbol label):

@symbol_label || ' - ' || aggregate('routes', 'sum', $length, "condition" = @symbol_label AND "parcel_id" = @atlas_featureid)

enter image description here

Then you can edit the expression to make it read better:

@symbol_label || ' - Sum of length in parcel: ' || round(aggregate('routes', 'sum', $length, "condition" = @symbol_label AND "parcel_id" = @atlas_featureid )/1000,2) || 'km'

Then you get the follow for parcels 1 and 2:

Parcel 1: enter image description here

Parcel 2: enter image description here

7
  • I am having trouble reproducing your approach. Allthough I made the settings in the Atlas, my lines are not displayed after setting the combined rule from the picture. Is there any place i should be using the ""parcel_id" = @atlas_featureid" line? What could I have missend?
    – Marek
    Mar 26 at 7:31
  • maybe i should add that in my scenario the lines are crossing parcels and i have intersected them with the parcel layer, to get a truthful allocation... but that should not be the issue. To prove that there are lines I've temporarely made an extra rule... i.imgur.com/pOAGKZI.png
    – Marek
    Mar 26 at 7:53
  • 1
    The field name I used is "parcel_id" but I see now you use "parcel", so use "parcel" = @atlas_featureid instead Mar 26 at 13:00
  • Sorry for the stupid question, but where do I use: "parcel" = @atlas_featureid? I wrote - "condition" = 'road' AND @atlas_featureid in ("parcel") - in the filtersettings but am a little lost where do i put the other rule...
    – Marek
    Mar 26 at 13:41
  • Hey TeddyTedTed, thank you for your help so far, but I am just not getting any lines displayed with the rule. Do you stil have the project saved so i could dowload it and learn, where my mistake is?
    – Marek
    Mar 26 at 21:33
1
+50

Thanks to TeddyTedTeds excellent answer I was able to reproduce the steps.

My data looks like this:

parcels is a polygon layer that contains the parcels. Attributes are parcel_id and parcel_name. Name is only used for labeling.

linear_ways is the ways layer. Its attributes are parcel_id as a reference of the parcel the way is inside of and condition which is a string that is set to "road" or "path".

I used "condition"='road' and "parcel_id" = @atlas_pagename as a symbology rule and it works for me.

Note I use @atlas_pagename and the original answer uses @atlas_featureid.

A trick I used was to use one rule to get the symbology showing in QGIS without using the atlas, that is only "condition" = 'road', add another symbology rule that has the expression "condition" = 'road' and "parcel_id" = @atlas_pagename . Same for path. Thus I verified that the rules worked in principle without an atlas.

symbology rules

Then I switched to the atlas versions of the rules and setup the atlas.

In the atlas setup be sure to set the pagename to the parcel_id.

atlas properties

I verified that the pagename is set correctly by using a label field with the expression [%concat('Atlas: ', @atlas_pagename )%] on the print layout.

Then I setup the map on the print layout to be controlled by the atlas.

map properties

I setup the aggregate legend the same as TeddyTedTed (again using @atlas_pagename instead), and this is the result:

result, works as expected

Note that your map units may not be (kilo)meters if your layer/project is using a CRS in feet or in degrees.

Make sure you export your atlas using the Atlas menu:

atlas menu

update: adding a filter to only populated parcels

I created a virtual integer field on the parcels layer named has_ways_inside that uses the expression overlay_contains( 'linear_ways'). This will evaluate to 1 or 0 depending on whether any features from the linear_ways layer are contained inside the parcel.

field calculator setup for virtual field

To only populate the atlas with parcels that have at least one way inside you also need to think about whether you want to display those empty parcels and just not generate an atlas page for them, or if you want to hide them completely.

To hide empty parcels completely, symbolize your parcels layer on has_ways_inside=1 in a rule-based symbolizer, or simply use a categorized symbolizer on the field and uncheck the 0 symbol.

I go with "display empty parcels, just not generate an altas page".

This then gets as simple as creating a coverage layer filter of "has_ways_inside" = 1:

atlas properties with coverage filter

3
  • Hello til_b. Thank your for the reply. I am not sure why it didn't work with the @atlas_featureid setting but this finally worked :) Thank you and TeddyTedTed for your help and time! now i can show off your skills ;)
    – Marek
    Apr 3 at 6:30
  • is there a way to filter the atlas result to only parcels that contain either one or both of the roadtypes? So i don'T have to export all parcels that are empty...?
    – Marek
    Apr 3 at 7:14
  • 1
    I would preprocess a field with this information (using a modeled workflow probably, because it uses select by location) and then filter the atlas coverage layer on the new field. Will enhance my answer hopefully later to reflect that.
    – til_b
    Apr 3 at 15:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.