Home
Softono

Qgis Expressions

Open source
245
Stars
28
Forks
0
Issues
12
Watchers
5 months
Last Commit

 About Qgis Expressions

Express yourself (in QGIS)

Platforms

Web Self-hosted

Links

Need Help Installing Qgis Expressions?

We provide expert installation service for this software. Our team will install, configure, and secure Qgis Expressions on your server. plans start at just $30.

Qgis Expressions

View on GitHub

qgis-expressions

My most used QGIS expressions, plus style files and screenshots.

See the full list of qgis expressions: Function list.

TABLE OF CONTENTS

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

Make

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

Scale labels in ortho projection

with_variable(
  'lat0',
  radians(to_real(regexp_replace(@project_crs_proj4, '.*\+lat_0=([-0-9.]+).*', '\\1'))),
  with_variable(
    'lon0',
    radians(to_real(regexp_replace(@project_crs_proj4, '.*\+lon_0=([-0-9.]+).*', '\\1'))),
    with_variable(
      'pt_ll',
      transform($geometry, @layer_crs, 'EPSG:4326'),
      with_variable(
        'lat',
        radians(y(@pt_ll)),
        with_variable(
          'lon',
          radians(x(@pt_ll)),
          with_variable(
            'ang',
            degrees(
              acos(
                sin(@lat0) * sin(@lat) +
                cos(@lat0) * cos(@lat) * cos(@lon - @lon0)
              )
            ),
            case
              when @ang > 90 then 0
              else scale_linear(@ang, 0, 90, 600000, 6000)
            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))