1

I am making a document with descriptions of how to get to some points of interest. For each point I am making a document that contains two maps, one showing the general overview and the larger roads (Typically scale 1:50000 - 1:100000) and another map showing a more detailed map close to the point of interest and the smaller roads or paths to get there (typically scale > 1:10000)

As the exact area I want to use in each map depends on the way the road network is around the point, it i not possible to calculate the mapextent from the point, but I can draw two polygons for each point indiating the overview area and the local area for each point.

So my question is:

Is it possible to make an atlas where I am using two different data sets to define the area covered by two different maps on one page?

Or do I have to make two different atlas and combine the maps when I am making the final document?

  • 3
    Who ever downvoted this, could you pleas explain why? – MortenSickel Apr 1 at 8:51
  • +1 to rebalance and answer – J. Monticolo Apr 1 at 9:25
3

Create your atlas with your Point Of Interest layer as coverage layer. For each of the two maps, make them controlled by the atlas and fix their scales.

If you want different scales from one POI to another, create two integer fields in the coverage layer for each map scale. You can define after the scale of each map in the control by attribute dropdown by :

attribute(@atlas_feature, 'large_scale_field')
0

I needed a bit more customisation than what Monticolo's answer would allow, so this is what I ended up doing. For each page in the atlas, defined by the detail map, find the corresponding polygon in the overview data set, set the extent of the overview map using the overview polygon. (And in case the overview polygon does not exist, use the same extent on both maps)

I do not want the shape of the overview map to change, therefore I am adjusting the bounding box to fit into the size of the defined overview map.

@qgsfunction(args='auto', group='Custom')
def getextent(feature,parent):
    overviewlayername='punkt_oversikt'
    layoutname='detaljkart-atlas'
    searchfield='navn'
    overviewmap='Hovedkart'
    detailmap='Detaljkart'
    projectInstance= QgsProject.instance()
    projectLayoutManager = projectInstance.layoutManager()
    layout=projectLayoutManager.layoutByName(layoutname)
    atl=layout.atlas()
    pg=atl.nameForPage(atl.currentFeatureNumber()) # The same as returned by @atlas_pagename
    ovLayer = QgsProject.instance().mapLayersByName(overviewlayername)[0] # The one and only
    xpr='"{}" = \'{}\''.format(searchfield,pg) # Search string - same format as used in filter
    expr = QgsExpression(xpr)
    it = ovLayer.getFeatures( QgsFeatureRequest( expr ) ) 
    n=0
    for item in it: # Only one item is to be expected
        n+=1
        bb=item.geometry().boundingBox()
    if n==0: 
        # In case no items are found, use the same extent for both maps
        detmap=layout.itemById(detailmap)
        bb=detmap.extent()
    xmax=bb.xMaximum()
    ymax=bb.yMaximum()
    xmin=bb.xMinimum()
    ymin=bb.yMinimum()
    aspect=bb.width()/bb.height()
    ovmap=layout.itemById(overviewmap)
    ovbb=ovmap.extent()
    ovaspect=ovbb.width()/ovbb.height()
    if ovaspect>aspect: # Want to put a map into an layoutitem that is too wide
        fact=ovaspect/aspect
        adj=bb.width()*(fact-1)/2
        xmin=xmin-adj
        xmax=xmax+adj
    else: # Want to put a map into an layoutitem that is too high
        fact=aspect/ovaspect
        adj=bb.height()*(fact-1)/2
        ymin=ymin-adj
        ymax=ymax+adj
    bbox=QgsRectangle(xmin,ymin,xmax,ymax)
    ovmap.setExtent(bbox)
    return "" # This is called from a textbox -

The function is being called by an invisible textbox. I have to look into a more elegant solution, but that is another question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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