0

I am making a A0 size poster map and need a very detailed basemap. Is there a way to lock the OpenStreetMap basemap to a certain scale/zoom so that it would be very detailed in the final print map? I can only get it to print in a big scale which simplifies the map a lot. The area I need to map is fairly big but I need it to still be detailed. I'm using QGIS but have access to ArcGis Pro as well.

  • The title suggests that you read the basemap from a WMS Service, is that right? Does it matter that if you use a very detailed scale on the printout the texts will be very tiny if you are not lucky enough to deal with a WMS server that supports some tricks for handling that issue? – user30184 Jan 8 at 11:20
  • Yes, I now realize that is true, the text will probably be way too small to read. Any tips on how to make a large map with lots of detail in A0 size? I probably need to find a raster or vector layer with the amount of detail I want. Shame I can't just use a WMS layer. – UniStudent Jan 8 at 11:39
  • 1
    did you increase the DPI in the map layout and does your WMS support DPI settings - GeoServer and MapServer do – Ian Turton Jan 8 at 11:41
  • 1
    If you can get ahold of the WMS service as XYZ Tiles instead then you have a bit more flexibility as you can set the min and max zoom levels, however there are trade-offs with this as well. – TeddyTedTed Jan 8 at 11:42
  • I can get a hold of XYZ Tiles but don't see how that is different? I also tried the WFS server but that seems like building a map from pretty much scratch and I can't get the place names to show as anything but points on the map. I tried increasing the DPI but maybe I'll try different settings with that if I manage to lock the scale. – UniStudent Jan 8 at 12:00
1

I struggled around with the same problem: always getting unreadable text when printing WMS layers to poster format in QGIS.

Even though the reduction of the layout resolution (i.e. 150DPI) helps sometimes, I found a really nice solution by using the fantastic MapProxy web map proxy server.

Therefor I did some minor adjustments to enable an optional WMS-URL parameter called "minres", which locks the resolution to a specific value.

Here are my changes to 3 of the MapProxy Python files:

/site-packages/mapproxy/grid.py

    ...

    def get_affected_tiles(self, bbox, size, req_srs=None, minres=0): # added minres 

        src_bbox, level = self.get_affected_bbox_and_level(bbox, size, req_srs=req_srs, minres=minres) # added minres
        return self.get_affected_level_tiles(src_bbox, level)

    def get_affected_bbox_and_level(self, bbox, size, req_srs=None, minres=0): # added minres
        if req_srs and req_srs != self.srs:
            src_bbox = req_srs.transform_bbox_to(self.srs, bbox)
        else:
            src_bbox = bbox

        if not bbox_intersects(self.bbox, src_bbox):
            raise NoTiles()

        res = get_resolution(src_bbox, size)

        ## added code for minres
        if res < minres:
            res = minres
        ##

        level = self.closest_level(res)

        if res > self.resolutions[0]*self.max_shrink_factor:
            raise NoTiles()

        return src_bbox, level
    ...

/site-packages/mapproxy/layer.py

    ...

    def _image(self, query):
        ### added code for minres
        if not hasattr(query,'minres'):
            query.minres = 0
        ###
        try:
            src_bbox, tile_grid, affected_tile_coords = \
                self.grid.get_affected_tiles(query.bbox, query.size,
                                             req_srs=query.srs,minres=query.minres) # added "minres"
        except NoTiles:
            raise BlankImage()
        except GridError as ex:
            raise MapBBOXError(ex.args[0])
    ...

/site-packages/mapproxy/service/wms.py

    ...

    def map(self, map_request):
        self.check_map_request(map_request)

        params = map_request.params
        query = MapQuery(params.bbox, params.size, SRS(params.srs), params.format)
        ### added code for minres
        query.minres = int(map_request.params.get('minres','0').replace('?',''))
        ###

        if map_request.params.get('tiled', 'false').lower() == 'true':
            query.tiled_only = True
        orig_query = query

     ...

     def capabilities(self, map_request):
        # TODO: debug layer
        # if '__debug__' in map_request.params:
        #     layers = self.layers.values()
        # else:
        #     layers = [layer for name, layer in iteritems(self.layers)
        #               if name != '__debug__']

        if map_request.params.get('tiled', 'false').lower() == 'true':
            tile_layers = self.tile_layers.values()
        else:
            tile_layers = []

        service = self._service_md(map_request)

        ### added code for minres
        if 'minres' in map_request.raw_params:
            service['url'] = service['url'] + '?minres=' + map_request.raw_params['minres']
        ###

        root_layer = self.authorized_capability_layers(map_request.http.environ)

     ...

After all changes we can add "minres=xx" to the WMS URL to lock the layer resolution in QGIS:

http://localhost:8080/mapproxy/service_name/service?minres=10

Please don't ask me about the right "minres" value ... I always have to try different values to achieve the best result. :-)

| improve this answer | |
0

The unfortunate truth is that WMS basemaps are designed for on-screen viewing, not for printing. To make a good printed map, you usually have to design the whole thing, with separate layers and custom styling.

One workaround is to get a basemap without any labels (there are several in the expanded provider pack of the quickmapservices plugin). Then you add manually any labels that you absolutely have to have, and live without the rest. Of course you still have the tradeoff between [high resolution + basemap features too small] vs. [low resolution/pixelated + basemap features the right size].

But, with that workaround, you can get labels by loading features (eg roads, towns, etc) from a WFS, turning off the symbology and only using them for labels. That way the labels are applied on top of the features baked into the basemap, and you don't have to set custom symbology.

| improve this answer | |

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.