My most used QGIS expressions, plus style files and screenshots.
See the full list of qgis expressions: https://docs.qgis.org/3.34/en/docs/user_manual/expressions/functions_list.html.
Make snapped points by rounding
make_point(round($x/100)*100,round($y/100)*100)
Make points aligned to map window
# align vertically
make_point(($x-($x-(x(@map_extent_center)-(@map_extent_width/3)))),$y)
# align both ways
make_point(($x-($x-(x(@map_extent_center)-(@map_extent_width/3)))),round($y,1))
Make line
make_line($geometry,geometry(get_feature('jp_snap_labels','geonameid',
attribute($currentfeature,'geonameid'))))
make_line(centroid($geometry),geometry(get_feature('Citybike','STATION','Millennium Tower' )))
make_line(centroid($geometry),make_point((x(@map_extent_center)+(@map_extent_width/2)),y(@map_extent_center)))
make_line(centroid($geometry),project(centroid($geometry),$length,radians((atan((xat(-1)-xat(0))/(yat(-1)-yat(0)))) * 180/3.14159 + (180 *(((yat(-1)-yat(0)) < 0) + (((xat(-1)-xat(0)) < 0 AND (yat(-1) - yat(0)) >0)*2))))))
make_line($geometry,project($geometry,("wind_sp"*0.1),(radians("wind_dir"))))
make_line($geometry,overlay_nearest('metars',$geometry))
Make conditional line
CASE WHEN $x > x(@map_extent_center) THEN make_line($geometry,make_point((x(@map_extent_center)+(@map_extent_width/3)),$y))
ELSE make_line($geometry,make_point((x(@map_extent_center)-(@map_extent_width/3)),$y))
END
Make line from map center
make_line($geometry,project($geometry,2,radians(angle_at_vertex(make_line(@map_extent_center,$geometry),0))))
closest_point(exterior_ring(buffer(@map_extent_center,2)),$geometry)
make_line(closest_point(exterior_ring(buffer(transform(@map_extent_center,'EPSG:4326','EPSG:53029'),2)),$geometry),$geometry)
closest_point(boundary(buffer(@map_extent_center,(@map_extent_width/2.5))),$geometry)
Make line from geometry
line_interpolate_point((make_line($geometry,closest_point((boundary(buffer(geometry(get_feature(@mylayer1,@myfield1,@myvalue1)),3))),$geometry))),(length(make_line($geometry,closest_point((boundary(buffer(geometry(get_feature(@mylayer1,@myfield1,@myvalue1)),3))),$geometry)))/2))
make_line($geometry,line_interpolate_point((make_line($geometry,closest_point((boundary(buffer(geometry(get_feature(@mylayer1,@myfield1,@myvalue1)),3))),$geometry))),(length(make_line($geometry,closest_point((boundary(buffer(geometry(get_feature(@mylayer1,@myfield1,@myvalue1)),3))),$geometry)))/2)))
Make line from array
make_line(array_agg(translate($geometry, 0, raster_value('topo15_432', 1, $geometry) * 0.001), group_by:=$y))
Make dynamic triangle
make_triangle(translate(centroid($geometry),-2.5,0),translate(centroid($geometry),0,scale_linear("dem_mean",-1500,1500,0,5)),translate(centroid($geometry),2.5,0))
Make circle
# circle from map extent
make_circle(@map_extent_center,(@map_extent_height/3))
Make polygon
# make polygon from bounds
bounds(make_line(make_point(-180,-90),make_point(180,90)))
# make rectangle polygon from map extent
bounds(make_line(make_point(x(@map_extent_center) - (@map_extent_width/3), y(@map_extent_center) - (@map_extent_height/3)), make_point(x(@map_extent_center) + (@map_extent_width/3), y(@map_extent_center) + (@map_extent_height/3))))
# make polygon from map extent in any projection
make_polygon(make_line(
make_point(x(transform(make_point(x(@map_extent_center) - (@map_extent_width/3),y(@map_extent_center)),@map_crs,'epsg:4326')),y(transform(make_point(x(@map_extent_center),y(@map_extent_center) - (@map_extent_height/3)),@map_crs,'epsg:4326'))),
make_point(x(transform(make_point(x(@map_extent_center) - (@map_extent_width/3),y(@map_extent_center)),@map_crs,'epsg:4326')),y(transform(make_point(x(@map_extent_center),y(@map_extent_center) + (@map_extent_height/3)),@map_crs,'epsg:4326'))),
make_point(x(transform(make_point(x(@map_extent_center) + (@map_extent_width/3),y(@map_extent_center)),@map_crs,'epsg:4326')),y(transform(make_point(x(@map_extent_center),y(@map_extent_center) + (@map_extent_height/3)),@map_crs,'epsg:4326'))),
make_point(x(transform(make_point(x(@map_extent_center) + (@map_extent_width/3),y(@map_extent_center)),@map_crs,'epsg:4326')),y(transform(make_point(x(@map_extent_center),y(@map_extent_center) - (@map_extent_height/3)),@map_crs,'epsg:4326'))),
make_point(x(transform(make_point(x(@map_extent_center) - (@map_extent_width/3),y(@map_extent_center)),@map_crs,'epsg:4326')),y(transform(make_point(x(@map_extent_center),y(@map_extent_center) - (@map_extent_height/3)),@map_crs,'epsg:4326')))
))
Make polygon from grid of points (wave plot, ridge plot, seismic plot)
make_polygon(make_line(make_point(x_min(@map_extent),y_min(@map_extent)), array_agg(translate($geometry, 0, raster_value('topo15_432', 1, $geometry) * 0.001), group_by:=$y), make_point(x_max(@map_extent),y_min(@map_extent))))
Make wave
wave_randomized($geometry,1,3,0.03,0.1)
Make curved line using wave function
wave($geometry,length($geometry),-length($geometry)/10,strict:=true)
Intersection
# extent in epsg:4326
intersection($geometry, bounds(make_line(make_point(-180,-90),make_point(180,90))))
# extent in epsg:3857
intersection($geometry, bounds(make_line(make_point(-20037508.34 -20048966.1),make_point(20037508.34 20048966.1)))
# map extent using buffer
intersection($geometry,buffer(@map_extent,-(@map_extent_height/4)))
# map extent using bounds
intersection($geometry,bounds(make_line(make_point(x(@map_extent_center) - (@map_extent_width/6), y(@map_extent_center) - (@map_extent_height/3)), make_point(x(@map_extent_center) + (@map_extent_width/6), y(@map_extent_center) + (@map_extent_height/3)))))
# frame rectangle from map extent
intersection($geometry, single_sided_buffer(boundary(@map_extent),(@map_extent_height/10)))
# frame circle from map extent
intersection($geometry, single_sided_buffer(boundary(buffer(@map_extent_center,(@map_extent_height/2))),-(@map_extent_height/10)))
# with feature geometry
intersection($geometry,aggregate('ne_110m_land','collect',$geometry))
# with hemispheres
intersection($geometry,make_polygon(make_line(make_point(-180,90),make_point(180,90),make_point(180,0),make_point(-180,0),make_point(-180,90))))
Difference
# make polygon between geometries and map extent
difference(@map_extent, aggregate(layer:='city_admin_levels', aggregate:='collect', expression:=$geometry, filter:=within($geometry,@map_extent)))
Multibuffer
collect_geometries(array_foreach(generate_series(0.1,1,0.01),buffer($geometry,@element)))
Extrude
extrude(boundary($geometry),0,0.2)
Translate geometries
# one axis
translate($geometry,0,scale_linear("meters",0,7800,0,2))
# splitscreen
translate(intersection($geometry, @map_extent), (@map_extent_width/2), 0)
# isometric (use with transform)
translate(smooth(simplify_vw($geometry,0),0), scale_linear("amax",0,4000,0,30) * -1, scale_linear("amax",0,4000,0,30) * -1)
# clip & move
translate(intersection($geometry,bounds(make_line(make_point(x(@map_extent_center) - (@map_extent_width/4), y(@map_extent_center) - (@map_extent_height/4)), make_point(x(@map_extent_center) + (@map_extent_width/4), y(@map_extent_center) + (@map_extent_height/4))))),0,-(@map_extent_height/4))
# create a geometry stack
collect_geometries(array_foreach(generate_series(0,to_int(replace(regexp_substr("other_tags",'(building:levels"=>"[0-9]+)'),'building:levels"=>"','')),1),translate($geometry,0,-@element)))
# create geometries at intervals using generate_series
collect_geometries(array_foreach(generate_series(0, eval(@qgis_25d_height), 1), translate( $geometry, cos( radians( eval( @qgis_25d_angle ) ) ) * @element, sin( radians( eval( @qgis_25d_angle ) ) ) * @element )))
Translate points by height (order by dem ascending)
translate(make_point(round(x($geometry),1),round(y($geometry),1)),-clamp(0,"dem"*0.0002,0.5),clamp(0,"dem"*0.0002,0.5))
Make 2.5d polygons (automatically filled in by qgis)
# top
translate( $geometry, cos( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height ), sin( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height ))
# sides
order_parts( extrude( segments_to_lines( $geometry ), cos( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height ), sin( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height ) ), 'distance( $geometry, translate( @map_extent_center, 1000 * @map_extent_width * cos( radians( @qgis_25d_angle + 180 ) ), 1000 * @map_extent_width * sin( radians( @qgis_25d_angle + 180 ) ) ))', False)
# shade sides
set_color_part( @symbol_color, 'value', 40 + 19 * abs( $pi - azimuth( point_n( geometry_n($geometry, @geometry_part_num) , 1 ), point_n( geometry_n($geometry, @geometry_part_num) , 2 ) ) ) )
# color sides by azimuth
set_color_part(ramp_color(@color, scale_linear(azimuth( point_n( geometry_n($geometry, @geometry_part_num) , 1 ), point_n( geometry_n($geometry, @geometry_part_num) , 2 ) ) / $pi, 0, 2, 0, 1)), 'alpha', 50)
# render order (descending)
distance( $geometry, translate( @map_extent_center, 1000 * @map_extent_width * cos( radians( @qgis_25d_angle + 180 ) ), 1000 * @map_extent_width * sin( radians( @qgis_25d_angle + 180 ) ) ))
# fix render order using y_max (not perfect)
distance( make_point(x($geometry), y_max($geometry)), translate( @map_extent_center, 1000 * @map_extent_width * cos( radians( @qgis_25d_angle + 180 ) ), 1000 * @map_extent_width * sin( radians( @qgis_25d_angle + 180 ) ) ))
Randomly choose one side of 2.5d geometry
geometry_n(order_parts( extrude( segments_to_lines( $geometry ), cos( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height ), sin( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height ) ), 'distance( $geometry, translate( @map_extent_center, 1000 * @map_extent_width * cos( radians( @qgis_25d_angle + 180 ) ), 1000 * @map_extent_width * sin( radians( @qgis_25d_angle + 180 ) ) ))', False), rand(0,num_geometries(@geometry)))
Make progressively simpler/smoother geometries in an array
collect_geometries(array_foreach(generate_series(0,5), smooth(simplify_vw($geometry,@element),3)))
rand
rand(0,1) = 0
rand(0,2) IN (0,1)
Case conditional
CASE WHEN other_tags LIKE '%"amenity"=>"parking"%' THEN 1
ELSE 0
END
Color ramps
# ramp by variable
ramp_color(@mycolorramp1,scale_linear(elev,@mymin1,@mymax1,0,1))
# ramp with alpha
set_color_part(ramp_color(@mycolorramp1,scale_linear(elev,@mymin1,@mymax1,0,1)),'alpha',@myalpha1)
# conditional ramp (with layer variables)
CASE WHEN DN >= 0 THEN ramp_color(@mycolorramp1,scale_linear("DN",@mymin1,@mymax1,0,1))
ELSE ramp_color(@mycolorramp2,scale_linear("DN",@mymin2,@mymax2,0,1))
END
# conditional ramp from raster value
CASE WHEN raster_value('topo15_4320', 1, centroid($geometry)) > 0 THEN ramp_color('wiki-1.02', scale_linear(raster_value('topo15_4320', 1, centroid($geometry)),-1500,2000,0,1))
ELSE ramp_color('Mako', scale_linear(raster_value('topo15_4320', 1, centroid($geometry)),-6000,0,0,1))
END
# color by distance
ramp_color('YlOrRd',scale_linear(distance(aggregate(layer:='bangkok_lines',aggregate:='collect',expression:=$geometry),$geometry),0,500,1,0))
# color by distance from center
ramp_color('Spectral', scale_linear(distance(@geometry, @map_extent_center), 0, @map_extent_width / 6, 0, 1))
# scale transparency from map center to edge
set_color_part('#000', 'alpha', scale_exp(distance(@map_extent_center,$geometry),0,distance(@map_extent_center,make_point(x_max(@map_extent),y_max(@map_extent))),50,0,2))
# color features in map extent
CASE WHEN intersects($geometry,@map_extent) THEN ramp_color('Spectral',scale_linear((array_find(array_agg("hybas_id",filter:=intersects($geometry,@map_extent)),"hybas_id") + 1),1,array_length(array_agg("hybas_id",filter:=intersects($geometry,@map_extent))),0,1))
ELSE '255,255,255'
END
# make your own color ramp
ramp_color(
create_ramp(map(0,'0,0,0',1,'53,123,163')),scale_linear("upland_skm",0,1000,0,1))
Intersecting with features
intersects($geometry, aggregate(layer:='bangkok_toronto_polygons_admin_level', aggregate:='collect', expression:=$geometry, filter:=intersects($geometry, @map_extent_center) AND "admin_level" IN ('9')))
CASE WHEN intersects($geometry,geometry(get_feature('ne_10m_land','featurecla','Land'))) THEN 1
ELSE 0
END
Intersecting with map extent
# using distance
(@map_extent_width/3) > distance(centroid($geometry),@map_extent_center)
# using buffer
intersects($geometry,buffer(@map_extent_center,@map_extent_width/4))
# using line
intersects($geometry, bounds(make_line(make_point(x_min(@map_extent),y_min(@map_extent)),make_point(x_max(@map_extent),y_max(@map_extent)))))
# using rectangle
x($geometry) > (x(@map_extent_center) - (@map_extent_width/4)) AND
x($geometry) < (x(@map_extent_center) + (@map_extent_width/4)) AND
y($geometry) > (y(@map_extent_center) - (@map_extent_height/4)) AND
y($geometry) < (y(@map_extent_center) + (@map_extent_height/4))
# using projected rectangle
x(transform($geometry, 'EPSG:4326', @map_crs)) > (x(@map_extent_center) - (@map_extent_width/4)) AND
x(transform($geometry, 'EPSG:4326', @map_crs)) < (x(@map_extent_center) + (@map_extent_width/4)) AND
y(transform($geometry, 'EPSG:4326', @map_crs)) > (y(@map_extent_center) - (@map_extent_height/4)) AND
y(transform($geometry, 'EPSG:4326', @map_crs)) < (y(@map_extent_center) + (@map_extent_height/4))
# using percentages
x($geometry) > (x(@map_extent_center) + (@map_extent_width*(-0.2))) AND
x($geometry) < (x(@map_extent_center) + (@map_extent_width*(-0.1))) AND
y($geometry) > (y(@map_extent_center) + (@map_extent_height*(-0.3))) AND
y($geometry) < (y(@map_extent_center) + (@map_extent_height*(0.3)))
# preserving grid in any projection
x($geometry) > x(transform(make_point(x(@map_extent_center) - (@map_extent_width/3),y(@map_extent_center)),@map_crs,'epsg:4326')) AND x($geometry) < x(transform(make_point(x(@map_extent_center) + (@map_extent_width/3),y(@map_extent_center)),@map_crs,'epsg:4326')) AND y($geometry) > y(transform(make_point(x(@map_extent_center),y(@map_extent_center) - (@map_extent_height/3)),@map_crs,'epsg:4326')) AND y($geometry) < y(transform(make_point(x(@map_extent_center),y(@map_extent_center) + (@map_extent_height/3)),@map_crs,'epsg:4326'))
Offset from geometry
scale_linear(y($geometry),(y(@map_extent_center)-(@map_extent_width/2)),(y(@map_extent_center)+(@map_extent_height/2)),0,1000)
Majority filter
"SUBREGION" = majority("SUBREGION",filter:=intersects($geometry,@map_extent))
Percentage from top
round(((((y(@map_extent_center))+(@map_extent_height/2)-$y))/(@map_extent_height))*100) || '%'
Labels from make_line() for projections or curves
# use when x <= -160 or x >= 160
CASE WHEN x($geometry) >= 160 THEN smooth(make_line(translate($geometry,-20,0),translate($geometry,-10,0),$geometry),3)
WHEN x($geometry) <= -160 THEN smooth(make_line($geometry,translate($geometry,10,0),translate($geometry,20,0)),3)
ELSE smooth(make_line(translate($geometry,-10,0),$geometry,translate($geometry,10,0)),3)
END
# intersection with map extent
smooth(make_line(translate(centroid(intersection($geometry,@map_extent)),-20,0), translate(centroid(intersection($geometry,@map_extent)),0,0), translate(centroid(intersection($geometry,@map_extent)),20,0)),3)
# use make_line
smooth(make_line(translate(make_point(x(@map_extent_center),y(@map_extent_center)-(@map_extent_height/3)),-(@map_extent_height/3),(@map_extent_height/3)), translate(make_point(x(@map_extent_center),y(@map_extent_center)-(@map_extent_height/4)),-(@map_extent_height/3),(@map_extent_height/4)), make_point(x(@map_extent_center),y(@map_extent_center)-(@map_extent_height/3)), translate(make_point(x(@map_extent_center),y(@map_extent_center)-(@map_extent_height/4)),(@map_extent_height/3),(@map_extent_height/4)), translate(make_point(x(@map_extent_center),y(@map_extent_center)-(@map_extent_height/3)),(@map_extent_height/3),(@map_extent_height/3))),10)
# center of map (reverse for labels on the bottom)
boundary(make_circle(@map_extent_center,(@map_extent_height/3)))
reverse(boundary(make_circle(@map_extent_center,(@map_extent_height/3))))
Rotate labels
CASE WHEN "aspect" >= 0 AND "aspect" < 90 THEN scale_linear("aspect",0,90,350,360)
WHEN "aspect" >= 90 AND "aspect" < 180 THEN scale_linear("aspect",90,180,0,10)
WHEN "aspect" >= 180 AND "aspect" < 270 THEN scale_linear("aspect",180,270,170,180)
WHEN "aspect" >= 270 AND "aspect" < 360 THEN scale_linear("aspect",270,360,180,190)
ELSE 0
END
Place labels outside geometry
difference(@map_extent,$geometry)
intersection($geometry,minimal_circle(@atlas_geometry))
Make callout lines for labels
# align left or right
CASE WHEN x($geometry) >= x(@map_extent_center) THEN make_line($geometry,make_point(x(@map_extent_center)+(@map_extent_width/3),y($geometry)))
ELSE make_line($geometry,make_point(x(@map_extent_center)-(@map_extent_width/3),y($geometry)))
END
# align left or right and spread along y
CASE WHEN x($geometry) >= x(@map_extent_center) THEN make_line($geometry,make_point(x(@map_extent_center)+(@map_extent_width/6),y($geometry)),make_point(x(@map_extent_center) + (@map_extent_width/4),scale_linear(y($geometry),(y(@map_extent_center)-(@map_extent_height/3)),(y(@map_extent_center)+(@map_extent_height)/3),(y(@map_extent_center)-(@map_extent_height/2.5)),(y(@map_extent_center)+(@map_extent_height/2.5)))))
ELSE make_line($geometry,make_point(x(@map_extent_center)-(@map_extent_width/6),y($geometry)),make_point(x(@map_extent_center) - (@map_extent_width/4),scale_linear(y($geometry),(y(@map_extent_center)-(@map_extent_height/3)),(y(@map_extent_center)+(@map_extent_height)/3),(y(@map_extent_center)-(@map_extent_height/2.5)),(y(@map_extent_center)+(@map_extent_height/2.5)))))
END
Distribute graticule labels around map
"degrees" LIKE '%0' AND "direction" IN ('N','S') AND
(x($geometry) > (x(@map_extent_center) + (@map_extent_width/2.5)) OR x($geometry) < (x(@map_extent_center) - (@map_extent_width/2.5))) AND
(y($geometry) > (y(@map_extent_center) - (@map_extent_height/2.5)) AND y($geometry) < (y(@map_extent_center) + (@map_extent_height/2.5)))
Distribute ranked labels evenly
transform(smooth(make_line(make_point(-95,scale_linear("rank",1,10,50,45)), make_point(-85,scale_linear("rank",1,10,50,45)), make_point(-75,scale_linear("rank",1,10,50,45))),3),'ESRI:4326','EPSG:102010')
transform(smooth(make_line(make_point(scale_linear("row",1,52,-66,-127),50), make_point(scale_linear("row",1,52,-66,-127),55), make_point(scale_linear("row",1,52,-66,-127),60)),3),'ESRI:4326','EPSG:102010')
Calculate angle
(atan((xat(-1)-xat(0))/(yat(-1)-yat(0)))) * 180/3.14159 + (180 *(((yat(-1)-yat(0)) < 0) + (((xat(-1)-xat(0)) < 0 AND (yat(-1) - yat(0)) >0)*2)))
Conditional angles
CASE WHEN ("line_direction" > 0 AND "line_direction" < 45) OR ("line_direction" > 135 AND "line_direction" < 225) OR ("line_direction" > 315) THEN 0
WHEN ("line_direction" >= 45 AND "line_direction" <= 135) OR ("line_direction" >= 225 AND "line_direction" <= 315) THEN 315
ELSE 0
END
Order angles from center (for distributing labels evenly in a circle)
array_find(array_distinct(array_agg(expression:="id", filter:=intersects_bbox($geometry,@map_extent), order_by:=azimuth(@map_extent_center,(centroid($geometry))))),"id") + 1
Angle from geometry
angle_at_vertex(transform(make_line($geometry,translate($geometry,10,0)),'EPSG:4326','EPSG:53029'),1)
line_interpolate_angle(make_line(make_point(x($geometry),y($geometry)),make_point((x(@map_extent_center)+(@map_extent_width/2)),y(@map_extent_center))),10)+270
angle_at_vertex(intersection(@map_extent,smooth($geometry,1)),(num_points(intersection(@map_extent,smooth($geometry,1)))/2))-90
Project
azimuth(transform($geometry,'EPSG:4326','+proj=vandg +lon_0=0 +x_0=0 +y_0=0 +R_A +a=6371000 +b=6371000 +units=m no_defs'), translate(transform($geometry,'EPSG:4326','+proj=vandg +lon_0=0 +x_0=0 +y_0=0 +R_A +a=6371000 +b=6371000 +units=m no_defs'),0,1))
make_line($geometry, project($geometry,1,radians("wind_dir_degrees")))
Rotate
(((x($geometry) - x(@map_extent_center))*cos(radians(@mydegrees))) - ((y($geometry) - y(@map_extent_center))*sin(radians(@mydegrees)))) + x(@map_extent_center)
(((x($geometry) - x(@map_extent_center))*sin(radians(@mydegrees))) + ((y($geometry) - y(@map_extent_center))*cos(radians(@mydegrees)))) + y(@map_extent_center)
Get coordinates from top-left (0,0)
round(((((x(@map_extent_center))-(@map_extent_width/2)-$x))/(-@map_extent_width))*100) || '|' ||
round(((((y(@map_extent_center))+(@map_extent_height/2)-$y))/(@map_extent_height))*100) || '|'
Odd & even fields
# odd columns
floor( $id / number_of_columns ) % 2 = 1
# even columns
floor( $id / number_of_columns ) % 2 = 0
Scale based on vertex number
scale_linear(@geometry_point_num,1,10,0.5,0.1)
Aspect coloring (hillshade from north)
CASE WHEN "aspect_mean" < 90 THEN ramp_color(@color_aspect,scale_linear("aspect_mean",0,89,0,0.5))
WHEN "aspect_mean" >= 90 AND "aspect_mean" < 180 THEN ramp_color(@color_aspect,scale_linear("aspect_mean",90,179,0.5,1))
WHEN "aspect_mean" >= 180 AND "aspect_mean" < 270 THEN ramp_color(@color_aspect,scale_linear("aspect_mean",180,269,1,0.5))
WHEN "aspect_mean" >= 270 THEN ramp_color(@color_aspect,scale_linear("aspect_mean",270,359,0.5,0))
END
Dynamic image source for raster fill
'/home/steve/base-maps/hillshade/places/' || "name" || '.png'
Delete english characters
regexp_replace("name", '[0-9A-Za-z;.,\\?\\/\\-\\(\\)ºçàèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝâêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿÄËÏÖÜŸěǎāīū]' , '' )
regexp_replace("name", '[0-9A-Za-z;\\?\\/\\-\\(\\)]' , '' )
Multiple replace
replace(replace(replace(replace(replace(replace(replace("namelsad", ' Urban Cluster', ''), ' Urbanized Area', ''), '--', '_'), '-', '_'), ' ', '_'), ',', ''), '/', '_')
Translate by replace
replace(replace(replace(replace(replace(replace(replace(replace(replace("featureclass",'A','境'),'H','水'),'L','区'),'P','位'),'R','路'),'S','点'),'T','山'),'U','海'),'V','卉')
Get sentence
substr("field_4",strpos("field_4",'\\.')+2,strpos(substr("field_4",strpos("field_4",'\\.')+2,200),'\\.'))
Get nth word
regexp_substr("point_tags", '^(?:\\S+\\s){0}(\\S+)')
regexp_substr("ECO_NAME",'([^( ]*)$')
Add space/newline between characters
regexp_replace("Cls",'([A-Z])','\\1 ')
regexp_replace("zh",'(.)','\\1\n')
Extract & replace
# building height, levels
replace(regexp_substr("other_tags",'(height"=>"[0-9]+\\.[0-9]+)'),'height"=>"','')
replace(regexp_substr("other_tags",'(building:levels"=>"[0-9]+)'),'building:levels"=>"','')*10
# address
replace(regexp_substr("other_tags",'(addr:housenumber"=>"[1-9]{1,3})'),'addr:housenumber"=>"','')
Ascii symbols from aspect
CASE WHEN "aspect_mean" >= 0 AND "aspect_mean" < 22.5 THEN '→'
WHEN "aspect_mean" >= 22.5 AND "aspect_mean" < 67.5 THEN '\\'
WHEN "aspect_mean" >= 67.5 AND "aspect_mean" < 112.5 THEN '|'
WHEN "aspect_mean" >= 112.5 AND "aspect_mean" < 157.5 THEN '/'
WHEN "aspect_mean" >= 157.5 AND "aspect_mean" < 202.5 THEN '—'
WHEN "aspect_mean" >= 202.5 AND "aspect_mean" < 247.5 THEN '\\'
WHEN "aspect_mean" >= 247.5 AND "aspect_mean" < 292.5 THEN '|'
WHEN "aspect_mean" >= 292.5 AND "aspect_mean" < 337.5 THEN '/'
ELSE '—'
END
CASE WHEN "aspectmean" >= 0 AND "aspectmean" < 90 THEN '\\'
WHEN "aspectmean" >= 90 AND "aspectmean" < 180 THEN '/'
WHEN "aspectmean" >= 180 AND "aspectmean" < 270 THEN '\\'
ELSE '/'
END
One-to-many relation (project properties > relations)
relation_aggregate('contour_gbif','min',"vname_en")
relation_aggregate('contour_gbif','concatenate',"vname_en",',')
Aggregate
aggregate(layer:='ne_10m_airports_snap1',aggregate:='concatenate',expression:="abbrev",filter:="scalerank" IS NOT NULL,concatenator:='\n')
aggregate(layer:='places_3857',aggregate:='concatenate',expression:="name",filter:=intersects($geometry,buffer(@map_extent_center,100000)),concatenator:='\n')
aggregate(layer:='wwf_terr_ecos_3857',aggregate:='concatenate_unique',expression:="ECO_SYM" || ' ' || "ECO_NAME",filter:=intersects($geometry,@map_extent),concatenator:='\n')
aggregate(layer:='places_3857',aggregate:='concatenate',expression:="name",filter:="iso_a2" = attribute(@atlas_feature,'iso_a2'),concatenator:='\n')
array_find(array_agg("fid", group_by:="ADM0_A3", order_by:="POP_MAX"), "fid")
intersects($geometry,aggregate('ne_50m_admin_0_map_subunits','collect',$geometry,intersects($geometry,@map_extent_center)))
aggregate(layer:='bangkok_toronto_points_neighbourhoods_3857', aggregate:= 'concatenate', filter:=intersects($geometry,@map_extent), expression:= trim(eval(array_find(array_distinct(array_agg(expression:="ogc_fid", filter:=intersects($geometry,@map_extent), order_by:=$x)),"ogc_fid") + 1) || ' ' || "name" || '\n'), order_by:=$x)
Aggregate legend
trim(replace(wordwrap(replace(replace(aggregate('places',aggregate:='concatenate',expression:="name" || ' ' || round("longitude") || '°,' || round("latitude") || '°@',filter:="scalerank" IN (0,1,2,3,4,5) AND
(@map_extent_width/3) > distance(centroid($geometry),@map_extent_center),order_by:="name"
),' ','_'),'@',' '),50),'_',' '))
Get attribute
attribute(get_feature('admin1_clean',$geometry,closest_point(geometry(get_feature('admin1_clean','enwiki_title',IS NOT NULL)),$geometry)),'enwiki_title')
aggregate(layer:='ne_50m_admin_0_countries',aggregate:='concatenate',expression:="CONTINENT",filter:=intersects($geometry,@map_extent_center),concatenator:=' ') || '\n' || wordwrap("_ECO_NAME",20) || '\n1:' || format_number(@map_scale,0)
Get array
replace(replace(array_to_string(array_slice(string_to_array(attribute(@atlas_feature,'geonames_mt')),0,9)),'{',''),'"','')
Get random character from array
array_get(array('□','▢','▣','▤','▥','▦','▧','▨','▩','▪','▫','◯','◉','◌','◍','◎','◐','◑','◒','◓','◔','◕','◖','◗','◘','◙','◚','◛','◜','◝','◞','◟','◠','◡','◢','◣','◤','◥','◦','◧','◨','◩','◪','◫','◬','◭','◮','◯','◰','◱','◲','◳','◴','◵','◶','◷','◸','◹','◺','◻','◼','◽','◾','◿'),rand(0,63))
Generate series and check array
array_contains(generate_series(1,maximum("fid"),(maximum("fid")/10)),"fid")
Get attribute matching name
attribute(get_feature('puma2020_nyc','name',"name"), 'pop2020')
Enumerate features in extent
(array_find(array_distinct(array_agg(expression:="ECO_ID", filter:=intersects_bbox($geometry,@map_extent), order_by:="ECO_NAME")),"ECO_ID") + 1)
aggregate(layer:='wwf_terr_ecos_3857',aggregate:='concatenate_unique',expression:='⬜ ' || (array_find(array_agg(expression:="ECO_NAME", filter:=intersects($geometry,@map_extent) AND $area >= '2500000000'), "ECO_NAME") + 1) || ' ' || "ECO_NAME",filter:=intersects($geometry,@map_extent) AND $area >= '2500000000',concatenator:='\n',order_by:="ECO_NAME")
Get attribute of geometry expression
"SUBREGION" = array_to_string(array_agg(expression:="SUBREGION", filter:=intersects($geometry,@map_extent_center)))
Get array of names of nearest features
array_to_string(overlay_nearest(layer:='bangkok_points', expression:="name", filter:=other_tags LIKE '%station"=>"subway"%', limit:=1))
Format large numbers
wordwrap("name",15) || '\n' ||
CASE WHEN length("pop_max") = 4 THEN left("pop_max",1) || 'k'
WHEN length("pop_max") = 5 THEN left("pop_max",2) || 'k'
WHEN length("pop_max") = 6 THEN left("pop_max",3) || 'k'
WHEN length("pop_max") = 7 THEN left("pop_max",1) || 'm'
WHEN length("pop_max") = 8 THEN left("pop_max",2) || 'm'
WHEN length("pop_max") = 9 THEN left("pop_max",3) || 'm'
ELSE "pop_max"
END
HTML labels (check allow html formatting)
'<p style="font-family:Montserrat; font-size:12pt; font-weight:600; color: #333;">' || "name" || '</p><p style="font-family:Montserrat; font-weight:300; font-size:10pt; color: #666;">' || format_number("elevation",0) || 'm</span>'
Make your own legend with HTML
'<p style="font-size:8pt; font-weight:500;">MEDIAN AGE BY COUNTY</p><p><span style="color:#D9D9D9;">⬛</span> <span>21 - 38 </span></p>
<p><span style="color:#C2CBCD;">⬛</span> <span>39 - 41</span></p>
<p><span style="color:#9CB4B7;">⬛</span> <span>42 - 44</span></p>
<p><span style="color:#76938E;">⬛</span> <span>45 - 68</span></p>'
Variables
"_CONTINENT" || '_' || "adm0name" || '_' || "adm1name" || '_' || "name" || '_' || round(map_get(item_variables('Map 1'),'map_extent_width') / 3)
replace("_CONTINENT" || '_x_' || round("longitude") || '_y_' || round("latitude") || '_width_' || round(map_get(item_variables('Map 1'),'map_extent_width')) || '_height_' || round(map_get(item_variables('Map 1'),'map_extent_height')),' ','_')
replace(replace("_CONTINENT" || '@' || "biome" || '@' || "adm0name" || '_x_' || round("longitude",2) || '_y_' || round("latitude",2) || '_width_' || round(map_get(item_variables('Map 1'),'map_extent_width'),2) || '_height_' || round(map_get(item_variables('Map 1'),'map_extent_height'),2),' ','_'),'/','_')
Example of map variables in filename
# get extent
lower(replace(replace("name",' ','_'),'.','')) || '_' || round(x_min(map_get(item_variables('Map 1'),'map_extent'))) || '_' || round(x_max(map_get(item_variables('Map 1'),'map_extent'))) || '_' || round(y_min(map_get(item_variables('Map 1'),'map_extent'))) || '_' || round(y_max(map_get(item_variables('Map 1'),'map_extent')))
# variable names
lower(replace(replace("name",' ','_'),'.','')) || '-' || lower(replace(replace("adm0name",' ','_'),'.',''))
leading zeroes in filename
'frame_' || lpad(@atlas_featurenumber, 4, '0')
Scale with map id
1:[% format_number(map_get(item_variables( 'map1' ), 'map_scale'),0) %]
Regex replace
regexp_replace(replace(@atlas_pagename, '.', ''), ' +', '_')
HTML labels
<p style="font-family:'Montserrat Thin';letter-spacing:10">WORLD MAP</p>
Layout projection
# by atlas feature
'PROJ:+proj=ortho +lat_0=' || y(centroid(buffer(@atlas_geometry,0))) || ' +lon_0=' || x(centroid(buffer(@atlas_geometry,0))) || ' +ellps=sphere'
# example of tilted perspective
'PROJ:+proj=tpers +tilt=0 +azi=10 +h=1000000000 +lon_0=0 +lat_0=-40 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs'
# continent
CASE WHEN attribute(@atlas_feature,'CONTINENT') IN ('Africa') THEN 'PROJ:+proj=ortho +lat_0="7" +lon_0="18" +ellps=sphere'
WHEN attribute(@atlas_feature,'CONTINENT') IN ('Asia','Oceania') THEN 'PROJ:+proj=ortho +lat_0="20" +lon_0="100" +ellps=sphere'
WHEN attribute(@atlas_feature,'CONTINENT') IN ('Europe') THEN 'PROJ:+proj=ortho +lat_0="30" +lon_0="30" +ellps=sphere'
WHEN attribute(@atlas_feature,'CONTINENT') IN ('North America') THEN 'PROJ:+proj=ortho +lat_0="68" +lon_0="-84" +ellps=sphere'
WHEN attribute(@atlas_feature,'CONTINENT') IN ('South America') THEN 'PROJ:+proj=ortho +lat_0="-18" +lon_0="-61" +ellps=sphere'
ELSE 'PROJ:+proj=ortho +lat_0=0 +lon_0=0 +ellps=sphere'
END
# subregion
CASE WHEN attribute(@atlas_feature,'subregion') IN ('Caribbean') THEN 'PROJ:+proj=ortho +lat_0=20 +lon_0=-75 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('Southern Europe') THEN 'PROJ:+proj=ortho +lat_0=41 +lon_0=7 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('Eastern Africa') THEN 'PROJ:+proj=ortho +lat_0=-4 +lon_0=37 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('Eastern Asia') THEN 'PROJ:+proj=ortho +lat_0=38 +lon_0=105 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('South America') THEN 'PROJ:+proj=ortho +lat_0=-15 +lon_0=-61 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('Australia and New Zealand') THEN 'PROJ:+proj=ortho +lat_0=-26 +lon_0=136 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('Antarctica') THEN 'PROJ:+proj=ortho +lat_0=-81 +lon_0=20 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('Western Africa') THEN 'PROJ:+proj=ortho +lat_0=15 +lon_0=-1 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('Melanesia') THEN 'PROJ:+proj=ortho +lat_0=-8 +lon_0=148 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('Southern Asia') THEN 'PROJ:+proj=ortho +lat_0=27 +lon_0=71 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('Eastern Europe') THEN 'PROJ:+proj=ortho +lat_0=61 +lon_0=92 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('Middle Africa') THEN 'PROJ:+proj=ortho +lat_0=1 +lon_0=19 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('Polynesia') THEN 'PROJ:+proj=ortho +lat_0=-15 +lon_0=-159 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('Central America') THEN 'PROJ:+proj=ortho +lat_0=22 +lon_0=-99 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('Northern Africa') THEN 'PROJ:+proj=ortho +lat_0=25 +lon_0=15 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('Central Asia') THEN 'PROJ:+proj=ortho +lat_0=46 +lon_0=66 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('Western Europe') THEN 'PROJ:+proj=ortho +lat_0=66 +lon_0=4 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('Western Asia') THEN 'PROJ:+proj=ortho +lat_0=28 +lon_0=43 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('Northern America') THEN 'PROJ:+proj=ortho +lat_0=59 +lon_0=-92 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('Northern Europe') THEN 'PROJ:+proj=ortho +lat_0=63 +lon_0=14 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('South-Eastern Asia') THEN 'PROJ:+proj=ortho +lat_0=8 +lon_0=110 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('Southern Africa') THEN 'PROJ:+proj=ortho +lat_0=-25 +lon_0=23 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('Seven seas (open ocean)') THEN 'PROJ:+proj=ortho +lat_0=-51 +lon_0=31 +ellps=sphere'
WHEN attribute(@atlas_feature,'subregion') IN ('Micronesia') THEN 'PROJ:+proj=ortho +lat_0=8 +lon_0=93 +ellps=sphere'
ELSE 'PROJ:+proj=ortho +lat_0=0 +lon_0=0 +ellps=sphere'
END
Change font, style, size with map id
# set @map_id to 'font_IBM Plex Sans_style_Regular_size_8_bgx_0_bgy_0.5_'
# font style
regexp_replace(regexp_replace(@map_id,'font_',''),'_.*$','')
Change page/layout size with atlas geometry (map scale 1:3000000)
# width
bounds_width(transform(@atlas_geometry,'EPSG:4326','EPSG:3857'))*0.001/3
# height
bounds_height(transform(@atlas_geometry,'EPSG:4326','EPSG:3857'))*0.001/3
XYZ Tiles
# google satellite
https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}
Python set skew variables
from qgis.core import QgsExpressionContextUtils
QgsExpressionContextUtils.setProjectVariable(QgsProject.instance(), 'skewx', 0.5)
QgsExpressionContextUtils.setProjectVariable(QgsProject.instance(), 'skewy', 0.5)
Grid 2.5d height from cloud cover raster
scale_linear(raster_value('CMC_glb_TCDC_SFC_0_latlon.15x.15_2024031500_P075', 1, centroid($geometry)),0,100,0,1)
Stacking symbols
translate(make_point(round(x($geometry),0),round(y($geometry),0)),0,scale_linear("dem",0,4000,0,4))
Rotate labels with aspect_lev06
CASE WHEN "aspect_lev06" >= 0 AND "aspect_lev06" < 45 THEN 350
WHEN "aspect_lev06" >= 45 AND "aspect_lev06" < 90 THEN 355
WHEN "aspect_lev06" >= 90 AND "aspect_lev06" < 135 THEN 5
WHEN "aspect_lev06" >= 135 AND "aspect_lev06" < 180 THEN 10
WHEN "aspect_lev06" >= 180 AND "aspect_lev06" < 225 THEN 350
WHEN "aspect_lev06" >= 225 AND "aspect_lev06" < 270 THEN 355
WHEN "aspect_lev06" >= 270 AND "aspect_lev06" < 315 THEN 5
WHEN "aspect_lev06" >= 315 AND "aspect_lev06" < 360 THEN 10
ELSE 0
END
Labels
CASE WHEN "xx" = 'ad' THEN 'Alluvial Deposits'
WHEN "xx" = 'ds' THEN 'Dune Sands'
WHEN "xx" = 'ev' THEN 'Evaporites'
WHEN "xx" = 'lo' THEN 'Loess'
WHEN "xx" = 'su' THEN 'Unconsolidated Sediments'
WHEN "xx" = 'sc' THEN 'Carbonate Sedimentary Rocks'
WHEN "xx" = 'sm' THEN 'Mixed Sedimentary Rocks'
WHEN "xx" = 'ss' THEN 'Siliciclastic Sedimentary Rocks'
WHEN "xx" = 'mt' THEN 'Metamorphic Rocks'
WHEN "xx" = 'pa' THEN 'Acid Plutonic Rocks'
WHEN "xx" = 'pi' THEN 'Intermediate Plutonic Rocks'
WHEN "xx" = 'pb' THEN 'Basic Plutonic Rocks'
WHEN "xx" = 'va' THEN 'Acid Volcanic Rocks'
WHEN "xx" = 'vi' THEN 'Intermediate Volcanic Rocks'
WHEN "xx" = 'vb' THEN 'Basic Volcanic Rocks'
WHEN "xx" = 'py' THEN 'Pyroclastics'
WHEN "xx" = 'wb' THEN 'Water Bodies'
WHEN "xx" = 'ig' THEN 'Ice and Glaciers'
WHEN "xx" = 'nd' THEN 'No Data'
ELSE ''
END
Tags
# Label english name if available
CASE WHEN "other_tags" LIKE '%name:en%' THEN regexp_replace(regexp_replace("other_tags",'^.*"name:en"=>"',''),'".*$','')
ELSE "name"
END
Highways
# color from field array
ramp_color('Spectral',scale_linear(array_find(array('motorway','trunk','primary','secondary','tertiary','residential'),"highway"),0,5,0,1))
Subways
# subway routes from multilinestrings
other_tags LIKE '%"route"=>"subway"%'
# subway station from points
other_tags LIKE '%station"=>"subway"%'
# buildings nearest to subway station
array_to_string(overlay_nearest(layer:='bangkok_points', filter:="other_tags" LIKE '%station"=>"subway"%', expression:="name")) = 'นานา'
# color buildings according to distance from subway station
ramp_color('Spectral',scale_linear(distance(geometry(get_feature('bangkok_subway_stations','name','นานา')),$geometry),0,1000,0,1))
Amenities
# parking
other_tags LIKE '%"amenity"=>"parking"%'
Buildings
# qgis_25d_height variable based on height or levels
CASE WHEN "other_tags" LIKE '%building:levels%' THEN replace(regexp_substr("other_tags",'(building:levels"=>"[0-9]+)'),'building:levels"=>"','')*10 WHEN "other_tags" LIKE '%height%' THEN replace(regexp_substr("other_tags",'(height"=>"[0-9]+)'),'height"=>"','')*5 ELSE 20 END
# make line from ground to label (200m)
extend(make_line(centroid(@geometry), translate( centroid(@geometry), cos( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height ), sin( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height ))), 0, scale_linear(y(@geometry),(y(@map_extent_center)-(@map_extent_height/4)),(y(@map_extent_center)+(@map_extent_height/4)), 0, 200))
# make line from roof to label (200m)
line_substring(extend(make_line(centroid(@geometry), translate( centroid(@geometry), cos( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height ), sin( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height ))), 0, 200), eval(@qgis_25d_height), eval(@qgis_25d_height) + 200)
# make line to distribute 2.5d labels based on y-axis (from 0 to 200m as you move farther back)
make_line(centroid(@geometry), translate( centroid(@geometry), cos( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height ) - scale_linear(y(@geometry),(y(@map_extent_center)-(@map_extent_height/4)),(y(@map_extent_center)+(@map_extent_height/4)),0,200), sin( radians( eval( @qgis_25d_angle ) ) ) * eval( @qgis_25d_height ) + scale_linear(y(@geometry),(y(@map_extent_center)-(@map_extent_height/4)),(y(@map_extent_center)+(@map_extent_height/4)),0,200)))
# make building floors
collect_geometries(array_foreach(generate_series(0,eval( @qgis_25d_height),10),segments_to_lines(translate( $geometry, cos( radians( eval( @qgis_25d_angle ) ) ) * @element, sin( radians( eval( @qgis_25d_angle ) ) ) * @element))))
GLAM/GLEAM map with light beam
# filter by glam tags
(other_tags LIKE '%"gallery"%' OR other_tags LIKE '%"library"%' OR '%"archive"%' OR other_tags LIKE '%"museum"%') AND name IS NOT NULL;
# create a layer variable 'beam_of_light' with this value
@map_extent_height - y($geometry)
Realms
CASE WHEN "REALM" = 'AA' THEN 'Australasia'
WHEN "REALM" = 'AN' THEN 'Antarctic'
WHEN "REALM" = 'AT' THEN 'Afrotropic'
WHEN "REALM" = 'IM' THEN 'Indomalaya'
WHEN "REALM" = 'NA' THEN 'Nearctic'
WHEN "REALM" = 'NT' THEN 'Neotropic'
WHEN "REALM" = 'OC' THEN 'Oceania'
WHEN "REALM" = 'PA' THEN 'Palearctic'
ELSE ''
END
Biomes
CASE WHEN "BIOME" = 1 THEN 'Tropical & Subtropical Moist Broadleaf Forests'
WHEN "BIOME" = 2 THEN 'Tropical & Subtropical Dry Broadleaf Forests'
WHEN "BIOME" = 3 THEN 'Tropical & Subtropical Coniferous Forests'
WHEN "BIOME" = 4 THEN 'Temperate Broadleaf & Mixed Forests'
WHEN "BIOME" = 5 THEN 'Temperate Conifer Forests'
WHEN "BIOME" = 6 THEN 'Boreal Forests/Taiga'
WHEN "BIOME" = 7 THEN 'Tropical & Subtropical Grasslands, Savannas & Shrublands'
WHEN "BIOME" = 8 THEN 'Temperate Grasslands, Savannas & Shrublands'
WHEN "BIOME" = 9 THEN 'Flooded Grasslands & Savannas'
WHEN "BIOME" = 10 THEN 'Montane Grasslands & Shrublands'
WHEN "BIOME" = 11 THEN 'Tundra'
WHEN "BIOME" = 12 THEN 'Mediterranean Forests, Woodlands & Scrub'
WHEN "BIOME" = 13 THEN 'Deserts & Xeric Shrublands'
WHEN "BIOME" = 14 THEN 'Mangroves'
ELSE ''
END
Control shading with slope
set_color_part('#000','alpha',scale_linear("slp_dg_sav",0,300,0,100))