Skip to content

Latest commit

 

History

History
920 lines (730 loc) · 41.8 KB

README.md

File metadata and controls

920 lines (730 loc) · 41.8 KB

qgis-expressions

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.

TABLE OF CONTENTS

  1. Make
  2. Calculate
  3. Strings
  4. Print layout
  5. Misc
  6. Datasets

make_point

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)))

Calculate

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))
# spectral
ramp_color(create_ramp(map(0,'215,48,39',0.1429,'215,48,39',0.2857,'252,141,89',0.4286,'254,224,144',0.5714,'255,255,191',0.7143,'224,243,248',0.8571,'145,191,219',1,'69,117,180')),scale_linear("scalerank",3,10,1,0))
# gebco-shelf
ramp_color(create_ramp(map(0,'0,240,255',0.0588,'35,255,255',0.1176,'35,255,255',0.1765,'90,255,255',0.2353,'90,255,255',0.2941,'140,255,230',0.3529,'140,255,230',0.4118,'165,255,215',0.4706,'165,255,215',0.5294,'195,255,215',0.5882,'195,255,215',0.6471,'210,255,215',0.7059,'210,255,215',0.7647,'230,255,240',0.8235,'230,255,240',0.8824,'235,255,255',0.9412,'235,255,255',1,'255,255,255')),randf(0,1))
# incandescent
ramp_color(create_ramp(map(0,'0,0,0',0.125,'93,0,0',0.25,'186,0,0',0.375,'221,69,25',0.5,'255,139,50',0.625,'251,189,34',0.75,'248,239,19',0.875,'249,243,116',1,'249,247,212')),randf(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)

# intersection with map extent (translate x and y)
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
boundary(make_circle(@map_extent_center,(@map_extent_height/3)))
# reverse for labels on the bottom
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'

Strings

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>'

Print layout

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(@atlas_geometry) || ' +lon_0=' || x(@atlas_geometry) || ' +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

Misc

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)

Datasets

GEM

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)

GeoNames

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

Global Lithological Map

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

OpenStreetMap

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)

WWF Ecoregions

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))