0

I have a temporary vector file from a qgis processing.run() (basically a line shapefile temporary output):

gis_osm_roads_free_1_lyr = results['Gis_osm_roads_free_1']

I have a map_item:

map_item = layout.itemById('Map 1')

I have a list of aspect ratios:

aspect_ratios = [(350, 300),(130,180), (180, 240), (150, 200), (150, 210)]

There are more of aspect ratio values but these are just for the question.

With all of these above I want to export a map with all of those different aspect ratios, a map that has gis_osm_roads_free_1_lyr in it.

So there is a function that sets the aspect ratio and then exports the map:

for aspect_ratio in aspect_ratios:

page_width, page_height = aspect_ratio

page_size = QgsLayoutSize(page_width, page_height)

layout.pageCollection().pages()[0].setPageSize(page_size)

ZoomExtent(page_height, scale, canvas, map_item)

# Create QgsLayoutSize for map item size

map_size = QgsLayoutSize(page_width, page_height)

map_item.attemptResize(map_size)

The issue:

"gis_osm_roads_free_1_lyr" presented in the map item is not perfectly fit to my map_item.

Even if I zoom to extent with PyQGIS it fits my layer width wise (but for all my aspect ratios width wise is always perfectly fit). Height wise I always have empty spaces above and below the layer.

Question:

How can I zoom automatically in order that my layer fits perfectly into map_item aspect ratio, height wise. It does not matter if I lose some of the data due to the zoom, but I would like that the layer covers perfectly the map_item height wise.

What I have tested:

canvas = iface.mapCanvas()
scale = canvas.scale()
scale_factor = page_height / canvas.height() # Used canvas height because layer extent equal to canvas extent.
new_scale = scale * scale_factor
canvas.zoomScale(new_scale)
map_item.refresh()

The formula for "new_scale" has no good correlation. For some cases it zooms too much and the scale factor value should be until top and bottom extent of layer match top and bottom extent of map_item.

2
  • 1
    It's impossible without distorting the map to force a bounding box to an aspect ratio. Accept that the width (or height) is correct and allow the other side to float to the necessary value
    – Ian Turton
    Commented Apr 20 at 17:09
  • I think that I can zoom in enough in order to cover whole map_item extent (with some of the vector data visibility loss which is ok). The map item height I know it from page_height variable, and the layer's height I think I can get it from a layer's bounding box. I do now know exactly how can I calculate a zoom factor based on this. Commented Apr 20 at 17:36

1 Answer 1

0

I have solved the issue ensuring my map fit properly within a specific layout on QGIS, here is the following code snippet:

canvas_extent = canvas.extent()
layout_aspect_ratio = page_width / page_height
canvas_aspect_ratio = canvas_extent.width() / canvas_extent.height()

if canvas_aspect_ratio > layout_aspect_ratio:
    zoom_factor = layout_aspect_ratio / canvas_aspect_ratio
else:
    zoom_factor = canvas_aspect_ratio / layout_aspect_ratio

new_width = canvas_extent.width() * zoom_factor
new_height = canvas_extent.height() * zoom_factor

new_center = canvas_extent.center()
new_extent = QgsRectangle(
    new_center.x() - new_width / 2,
    new_center.y() - new_height / 2,
    new_center.x() + new_width / 2,
    new_center.y() + new_height / 2
)

map_item.setExtent(new_extent)

Here's what the code does in detail:

  1. Calculate Aspect Ratios:

It calculates the aspect ratios of the layout (defined by page_width and page_height) and the current canvas.

  1. Determine Zoom Factor:

Depending on whether the canvas is wider or taller relative to the layout, it calculates a zoom factor to fit the canvas into the layout. This ensures that the map is scaled properly to fit within the layout dimensions without being distorted.

  1. Calculate New Dimensions:

It applies the zoom factor to the canvas dimensions to get the new width and height of the extent.

  1. Calculate New Extent:

It calculates the new extent by adjusting the center of the original extent. This is done by subtracting and adding half of the new width and height to the center coordinates, ensuring the new extent is centered correctly.

Hopefully It can be useful for other people that encounter this issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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