Make sure that the assigned CRS is set to EPSG:3005 and correct the value of your target EPSG.
![enter image description here](https://i.stack.imgur.com/yRqUT.png)
You should put this as a default values for your lon/lat fields, respectively :
format_number(x( transform( $geometry, layer_property(@layer,'crs'), 'EPSG:4326')),6)
format_number(y( transform( $geometry, layer_property(@layer,'crs'), 'EPSG:4326')),6)
The best solution I could find at the moment is to use the new SQLite JSON functions and operators (available since SQLite 3.38.0): https://www.sqlite.org/json1.html
So I changed my Python expression function to return a JSON string:
from qgis.core import qgsfunction,QgsProject,QgsExpressionContextUtils
@qgsfunction(args='auto', group='Custom')
def getLayoutMapGridParam(layoutname, feature, parent):
layout = QgsProject.instance().layoutManager().layoutByName(layoutname)
space = QgsExpressionContextUtils.projectScope(QgsProject.instance()).variable('grid_space')
print(space)
if not space:
space = 1000
QgsExpressionContextUtils.setProjectVariable(QgsProject.instance(), 'grid_space','1000')
else:
space = int(space)
if layout:
map = layout.referenceMap()
if map:
extent = map.extent()
xmin = int(extent.xMinimum()/space)*space
ymin = int(extent.yMinimum()/space)*space
xcount = round(extent.width()/space,0)+1
ycount = round(extent.height()/space,0)+1
return '{"xmin":%s,"ymin":%s,"xcount":%s,"ycount":%s,"space":%s}' % (xmin,ymin,xcount,ycount,space)
if not extent:
return None
and modified the SQL to use JSON operators:
WITH RECURSIVE
r(x) AS (
SELECT getLayoutMapGridParam('MyLayout') -> 'xmin'
UNION ALL
SELECT x+getLayoutMapGridParam('MyLayout')->'space' FROM r
LIMIT getLayoutMapGridParam('MyLayout') -> 'xcount'
),
c(y) AS (
SELECT getLayoutMapGridParam('MyLayout') -> 'ymin'
UNION ALL
SELECT y+getLayoutMapGridParam('MyLayout')->'space' FROM c
LIMIT getLayoutMapGridParam('MyLayout') -> 'ycount'
)
SELECT row_number() over() as id,geomfromtext('POINT('||r.x||' '||c.y||')',31255) as geom /*:point:31255*/ FROM r,c
The default grid spacing (1000) can be changed through setting the QGIS project variable grid_space
.
BTW: I'm using QGIS 3.26.3 on Windows (SQLite 3.38.1)
*** UPDATE ***
with a small change in our SQL code we can reduce the number of calls to the PYTHON function getLayoutMapGridParam
WITH RECURSIVE
data(xmin,ymin,xcount,ycount,space) AS MATERIALIZED
(SELECT
json->'xmin' AS xmin,
json->'ymin' AS ymin,
json->'xcount' AS xcount,
json->'ycount' AS ycount,
json->'space' AS space
FROM (SELECT getLayoutMapGridParam('MyLayout') AS json)),
r(x) AS (
SELECT xmin FROM data
UNION ALL
SELECT x+space FROM r,data
LIMIT (SELECT xcount FROM data)
),
c(y) AS (
SELECT ymin FROM data
UNION ALL
SELECT y+space FROM c,data
LIMIT (SELECT ycount FROM data)
)
SELECT row_number() over() as id,geomfromtext('POINT('||r.x||' '||c.y||')',31255) as geom /*:point:31255*/ FROM r,c
Best Answer
Seriously, I've had this problem all day, scouring google, 10 minutes after posting the question - of course, I stumble across the answer on the git forums.
The reason why this doesn't work is explained in detail here https://github.com/qgis/QGIS/issues/41695
In short, the Preview doesn't use the same code as the actual function method, and in order to get it to work, you need to declare
usesgeometry=True
in the function declaration.So this works.