4

I am trying to figure out how to set the zoom scales to match those meant for OpenStreetMaps and Google Maps, etc., as I am using OSM for a basemap. I've looked all over the internet and can't seem to find any support for this particular goal.

I have an XML document (scales.xml) with all of the scales needed, but I just can't figure out how to implement it:

<qgsScales version="1.0">
    <scale value="1:591657528"/>
    <scale value="1:295828764"/>
    <scale value="1:147914382"/>
    <scale value="1:73957191"/>
    <scale value="1:36978595"/>
    <scale value="1:18489298"/>
    <scale value="1:9244649"/>
    <scale value="1:4622324"/>
    <scale value="1:2311162"/>
    <scale value="1:1155581"/>
    <scale value="1:577791"/>
    <scale value="1:288895"/>
    <scale value="1:144448"/>
    <scale value="1:72224"/>
    <scale value="1:36112"/>
    <scale value="1:18056"/>
    <scale value="1:9028"/>
    <scale value="1:4514"/>
    <scale value="1:2257"/>
    <scale value="1:1128"/>
    <scale value="1:564"/>
    <scale value="1:282"/>
    <scale value="1:141"/>
    <scale value="1:71"/>
</qgsScales>

I've tried reworking some of the code from thr QuickMapServices plugin, but I get no results from it:

def _load_scales_list(self):
    scales_filename = os.path.join(self.plugin_dir, 'scales.xml')
    scales_list = []

    xml_root = ET.parse(scales_filename).getroot()
    for scale_el in xml_root.findall('scale'):
        scales_list.append(scale_el.get('value'))
    return scales_list

def scales_list(self):
    if not self._scales_list:
        self._scales_list = self._load_scales_list()
    return self._scales_list

def set_nearest_scale(self):
    #get current scale
    curr_scale = self.mapCanvas().scale()
    #find nearest
    nearest_scale = sys.maxint
    for scale_str in self.scales_list:
        scale = scale_str.split(':')[1]
        scale_int = int(scale)
        if abs(scale_int-curr_scale) < abs(nearest_scale - curr_scale):
            nearest_scale = scale_int

    #set new scale
    if nearest_scale != sys.maxint:
        self.mapCanvas().zoomScale(nearest_scale)

This code neither throws an error nor does anything at all. Any ideas as to how I can get this working in a standalone window?

0

2 Answers 2

4
+50

You should place the definition of the list of predefined scales in your init-method.

self.predefinedScale = [...]

Then connect the scaleChanged event to the function actually setting the proper scale.

self.mapCanvas.scaleChanged.connect(self.zoomToScale)

Define this function as class method, not as local function of some other method, so that it will be executed in the global context.

def zoomToScale(self)
    self.mapCanvas.scaleChanged.disconnect(self.zoomToScale)
    scale = self.mapCanvas.scale()
    targetScale = min(self.predefinedScales, key=lambda x: abs(x - scale))
    self.mapCanvas.zoomScale(targetScale)
    self.mapCanvas.scaleChanged.connect(self.zoomToScale)
0
3

you can define this scale in predefined scale for qgisenter image description here

USING Python :

def forcedScale(scales):
    def zoomToScale(scale):
        self.iface.mapCanvas().scaleChanged.disconnect(zoomToScale)
        targetScale = min(scales, key=lambda x:abs(x-scale))
        self.iface.mapCanvas().zoomScale( targetScale )
        self.iface.mapCanvas().scaleChanged.connect(zoomToScale)

    predefinedScales = [
        591657528,
        295828764,
        147914382,
        73957191,
        36978595,
        18489298,
        9244649,
        4622324,
        2311162,
        1155581,
        577791,
        288895,
        144448,
        72224,
        36112,
        18056,
        9028,
        4514,
        2257,
        1128,
        564,
        282,
        141,
        71
    ]

    self.iface.mapCanvas().scaleChanged.connect(zoomToScale)
    scales = predefinedScales
8
  • This is helpful for QGIS Desktop, but I'm coding out of the QGIS API. I need to figure out how to do this in python. Thanks though.
    – Alex92
    Oct 21, 2015 at 3:57
  • I tried your Python with a few changes, as the "iface" variable is not usable outside of QGIS proper. For the purposes of using this standalone, I changed all instances of "iface" to "self", and added "self" to the list of arguments in each definition. Also needed to add commas in the scales list. However, the code ends up not working, and my scales have not changed.
    – Alex92
    Oct 27, 2015 at 15:12
  • did you try to add print statement to check if this function is called ? because i tried this now it works for me. Oct 27, 2015 at 18:38
  • 1
    I did, and it appears the function is not called. Here is a link to a gist of my code. It begins at line 142. Could I have implemented it wrong?
    – Alex92
    Oct 27, 2015 at 20:13
  • you are not calling forcedScale anywhere in your code. call this function in main or somewhere else. Oct 27, 2015 at 21:18

Your Answer

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

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